beemhq / aws-cron-parser

A util to parse cron expressions used by AWS services

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Thank you!

amcdnl opened this issue · comments

I built one of these buts it not as good as yours, thank you for writing this! For fun, I included mine below.

export type IntervalTypes =
  | 'minute'
  | 'hour'
  | 'day'
  | 'week'
  | 'month'
  | 'year';

export type CronObject = {
  interval?: IntervalTypes;
  daysOfWeek?: number[];
  dayOfMonth?: number;
  timeOfDay?: any;
  month?: number;
  minute?: number;
  hour?: number;
};

/**
 * Given a CRON expression, build a CRON object.
 */
export const buildCronObject = (value: string) => {
  const result: CronObject = {};

  if (value) {
    const [minute, hour, day, month, dayOfTheWeek] = value.split(' ');
    const hasHour = hour !== '*';
    const hasMinute = minute !== '*';
    const hasMonth = month !== '*';
    const hasDayOfTheMonth = day !== '*';
    const hasDayOfTheWeek = dayOfTheWeek !== '?';

    if (hasHour && hasMinute && hasDayOfTheMonth && hasMonth) {
      result.interval = 'year';
      result.month = parseInt(month);
      result.timeOfDay = `${hour}:${minute}`;
      result.dayOfMonth = parseInt(day);
    } else if (hasHour && hasMinute && hasDayOfTheMonth) {
      result.interval = 'month';
      result.timeOfDay = `${hour}:${minute}`;
      result.dayOfMonth = parseInt(day);
    } else if (hasHour && hasMinute && hasDayOfTheWeek) {
      result.interval = 'week';
      result.timeOfDay = `${hour}:${minute}`;
      result.daysOfWeek = dayOfTheWeek.split(',').map(d => parseInt(d));
    } else if (hasHour && !hasMinute) {
      result.interval = 'hour';
      result.hour = parseInt(hour);
    } else if (hasHour && hasMinute) {
      result.interval = 'day';
      result.timeOfDay = `${hour}:${minute}`;
    } else if (minute) {
      result.interval = 'minute';
      const [, minuteInterval] = value.split('/');
      result.minute = parseInt(minuteInterval);
    }
  }

  return result;
};

/**
 * Given a CRON object, build a expression.
 */
export const buildCronExpression = ({
  interval,
  dayOfMonth,
  daysOfWeek,
  hour,
  minute,
  month,
  timeOfDay
}: CronObject) => {
  if (interval === 'minute') {
    if (minute) {
      return `0/${minute} * * * ? *`;
    }
  } else if (interval === 'hour') {
    if (hour) {
      return `* ${hour} * * ? *`;
    }
  } else if (interval === 'day') {
    if (timeOfDay) {
      const [hourOfDay, minuteOfHour] = timeOfDay.split(':');
      return `${minuteOfHour} ${hourOfDay} * * ? *`;
    }
  } else if (interval === 'week') {
    if (timeOfDay && daysOfWeek) {
      const [hourOfDay, minuteOfHour] = timeOfDay.split(':');
      const dayOfTheWeek = daysOfWeek.map(d => d.toString());
      return `${minuteOfHour} ${hourOfDay} * * ${dayOfTheWeek.join(',')} *`;
    }
  } else if (interval === 'month') {
    if (timeOfDay && dayOfMonth) {
      const [hourOfDay, minuteOfHour] = timeOfDay.split(':');
      return `${minuteOfHour} ${hourOfDay} ${dayOfMonth} * ? *`;
    }
  } else if (interval === 'year') {
    if (timeOfDay && dayOfMonth && month) {
      const [hourOfDay, minuteOfHour] = timeOfDay.split(':');
      return `${minuteOfHour} ${hourOfDay} ${dayOfMonth} ${month} ? *`;
    }
  }
};

and

import { buildCronObject, buildCronExpression } from './parser';

describe('CronInput', () => {
  it('should build every day at 12:00pm UTC', () => {
    const obj = buildCronObject('0 12 * * ? *');
    expect(obj.interval).toBe('day');
    expect(obj.timeOfDay).toBe('12:0');

    const result = buildCronExpression(obj);
    expect(result).toBe('0 12 * * ? *');
  });

  it('should build every day, at 5 and 35 minutes past 2:00pm UTC', () => {
    const obj = buildCronObject('5,35 14 * * ? *');
    expect(obj.interval).toBe('day');
    expect(obj.timeOfDay).toBe('14:5,35');

    const result = buildCronExpression(obj);
    expect(result).toBe('5,35 14 * * ? *');
  });

  it('should build every minute', () => {
    const obj = buildCronObject('0/1 * * * ? *');
    expect(obj.interval).toBe('minute');
    expect(obj.minute).toBe(1);

    const result = buildCronExpression(obj);
    expect(result).toBe('0/1 * * * ? *');
  });

  it('should build every 10 minutes Monday through Friday', () => {
    const obj = buildCronObject('15 5 * * 2,3,4,5,6 *');
    expect(obj.interval).toBe('week');
    expect(obj.timeOfDay).toBe('5:15');
    expect(obj.daysOfWeek[0]).toBe(2);
    expect(obj.daysOfWeek[1]).toBe(3);
    expect(obj.daysOfWeek[2]).toBe(4);
    expect(obj.daysOfWeek[3]).toBe(5);
    expect(obj.daysOfWeek[4]).toBe(6);

    const result = buildCronExpression(obj);
    expect(result).toBe('15 5 * * 2,3,4,5,6 *');
  });
});

That's a good first issue 😄 Thanks for the feedback and glad you're finding it useful!

It would be cool if we could merge some of that parsing I have with your lib.