Skip to content

Commit

Permalink
Add ability to count number of weeks and months
Browse files Browse the repository at this point in the history
  • Loading branch information
rautio committed Oct 15, 2023
1 parent dbc27aa commit 5cb410a
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 45 deletions.
2 changes: 1 addition & 1 deletion __tests__/parseText/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { readFileSync, readdirSync } from 'fs';
import { parseText } from '../../src/index';

const currentDate = new Date('2023-1-1');
const currentDate = new Date('2023-3-4');

const path = require('path');

Expand Down
24 changes: 18 additions & 6 deletions __tests__/parseText/suites/smoke.txt
Original file line number Diff line number Diff line change
Expand Up @@ -56,22 +56,22 @@ Every 12 hrs
0 */12 * * *

Tomorrow
0 9 2 * *
0 9 5 * *

In 3 days
0 9 4 * *
0 9 7 * *

in a day
0 9 2 * *
0 9 5 * *

In twenty days
0 9 21 * *
0 9 24 * *

next week
0 9 * * 1

next month
0 9 1 1 *
0 9 1 3 *

next Monday
0 9 * * 1
Expand All @@ -80,4 +80,16 @@ next Friday
0 9 * * 5

next weekend
0 9 * * 0,6
0 9 * * 0,6

in a month
0 9 4 3 *

in a week
0 9 11 * *

in 2 weeks
0 9 18 * *

in 5 months
0 9 4 7 *
85 changes: 55 additions & 30 deletions src/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,8 @@ export const INIT = '_'; // Used to know whether the value has been set at all.
export const DEFAULT_DAY_MINUTES = '0';
export const DEFAULT_DAY_HOURS = '9';

const {
FREQUENCY,
OCCURENCE,
NUMBER,
MINUTE,
CLOCK,
DAY,
HOUR,
DAYS,
RELATIVE_DAY,
} = TokenType;
const { FREQUENCY, NUMBER, MINUTE, CLOCK, DAY, HOUR, DAYS, RELATIVE_DAY } =
TokenType;

const defaultParsed: Parsed = {
minutes: INIT,
Expand All @@ -38,6 +29,51 @@ const defaultParsed: Parsed = {
month: INIT,
};

export const updateDays = (
crontext: Parsed,
tokens: Token[],
options: Options,
): Parsed => {
// Default like 'next week'
let delta = 1;
let setDate = true;
if (crontext.minutes === INIT) crontext.minutes = options.defaultMinute;
if (crontext.hour === INIT) crontext.hour = options.defaultHour;
// Specified the number like 'in 3 days', 'in 2 weeks', etc.
if (tokens.length === 3) {
delta = getNumber(tokens[1].value);
}
if (tokens[tokens.length - 1].value.indexOf('month') > -1) {
const nextDate = new Date(options.startDate.getTime());
nextDate.setMonth(nextDate.getMonth() + delta);
// 'next month'
if (crontext.dayOfMonth === INIT && tokens.length == 2) {
crontext.dayOfMonth = '1';
} else {
crontext.dayOfMonth = nextDate.getDate().toString();
}
return {
...crontext,
month: nextDate.getMonth().toString(),
};
}
// Day or week (month would have been returned above)
if (tokens[tokens.length - 1].value.indexOf('week') > -1) {
if (tokens.length === 2) {
crontext.dayOfWeek = '1';
setDate = false;
}
delta *= 7;
}
if (setDate) {
const { startDate } = options;
const nextDate = new Date(startDate.getTime());
nextDate.setDate(nextDate.getDate() + delta);
crontext.dayOfMonth = nextDate.getDate().toString();
}
return crontext;
};

/**
* -> [FREQ][COMBO1]
* [COMBO1] -> [(NUMBER)][MINUTE|HOUR|DAY]
Expand Down Expand Up @@ -77,19 +113,21 @@ export const rules = [
return crontext;
},
},
{
match: [FREQUENCY, DAYS],
update: updateDays,
},
{
match: [FREQUENCY, NUMBER, DAYS],
update: updateDays,
},
{
match: [FREQUENCY, DAY],
update: (crontext: Parsed, tokens: Token[], options: Options): Parsed => {
// If there are no minutes or hour set we use defaults
// 'On monday' -> 9am Monday
if (crontext.minutes === INIT) crontext.minutes = options.defaultMinute;
if (crontext.hour === INIT) crontext.hour = options.defaultHour;
if (tokens[1].value === 'month') {
if (crontext.dayOfMonth === INIT) crontext.dayOfMonth = '1';
const nextDate = new Date(options.startDate.getTime());
nextDate.setMonth(nextDate.getMonth() + 1);
return { ...crontext, month: nextDate.getMonth().toString() };
}
const dayOfWeek = getDayOfWeek(tokens[1].value);
return { ...crontext, dayOfWeek };
},
Expand All @@ -108,19 +146,6 @@ export const rules = [
return crontext;
},
},
{
match: [OCCURENCE, NUMBER, DAYS],
update: (crontext: Parsed, tokens: Token[], options: Options): Parsed => {
const delta = getNumber(tokens[1].value);
const { startDate } = options;
const nextDate = new Date(startDate.getTime());
nextDate.setDate(nextDate.getDate() + delta);
crontext.dayOfMonth = nextDate.getDate().toString();
if (crontext.minutes === INIT) crontext.minutes = options.defaultMinute;
if (crontext.hour === INIT) crontext.hour = options.defaultHour;
return crontext;
},
},
{
match: [FREQUENCY, CLOCK],
update: (crontext: Parsed, tokens: Token[]): Parsed => {
Expand Down
2 changes: 1 addition & 1 deletion src/tokens/day.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export const dayRegexOptions =
'month|(mon|tues|tue|wed|thurs|thur|fri|sat|sun)(day)?|week(day|end)?';
'^(mon|tues|tue|wed|wednes|thurs|thur|fri|sat|sun)(day)?$|weekday|weekend?$';

const weekMap: Record<string, string> = {
sun: '0',
Expand Down
10 changes: 3 additions & 7 deletions src/tokens/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ export enum TokenType {
NUMBER = 'number',
EXCLUDE = 'exclude',
FREQUENCY = 'frequency',
OCCURENCE = 'occurence',
DAY = 'day',
DAYS = 'days',
RELATIVE_DAY = 'relative day',
Expand Down Expand Up @@ -45,7 +44,7 @@ export const tokens = {
test: '^(hours|hour|hrs|hr)$',
},
[TokenType.DAYS]: {
test: '^(days|day)$',
test: 'month|^(days|day|foo|month|months|week|weeks)$',
},
[TokenType.RELATIVE_DAY]: {
test: '^(tomorrow)$',
Expand All @@ -54,16 +53,13 @@ export const tokens = {
test: `^(\\d+|${numberStringRegexOptions})$|^a$`,
},
[TokenType.FREQUENCY]: {
test: '^(every|each|every other|at|on|next)$',
},
[TokenType.OCCURENCE]: {
test: '^(in)$',
test: '^(every|each|every other|at|on|in|next)$',
},
[TokenType.CLOCK]: {
test: /^(\d?\d:\d\d|\d)[ ]?(am|pm|AM|PM)|\d\d:\d\d|midnight|noon$/,
},
[TokenType.DAY]: {
test: `^${dayRegexOptions}$`,
test: `${dayRegexOptions}`,
},
[TokenType.EXCLUDE]: {
test: '^(except|excluding)$',
Expand Down

0 comments on commit 5cb410a

Please sign in to comment.