Skip to content

Commit

Permalink
fix: DateTime.add() hangs when interval generates sequences never ove…
Browse files Browse the repository at this point in the history
…rlap byhour
  • Loading branch information
huaichaow committed Mar 26, 2024
1 parent 9f2061f commit 4a3a7d5
Show file tree
Hide file tree
Showing 2 changed files with 123 additions and 7 deletions.
38 changes: 31 additions & 7 deletions src/datetime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,12 @@ export class DateTime extends Time {
this.fixDay()
}

public addHours(hours: number, filtered: boolean, byhour: number[]) {
public addHours(
hours: number,
filtered: boolean,
byhour: number[],
until?: Date
) {
if (filtered) {
// Jump to one iteration before next day
this.hour += Math.floor((23 - this.hour) / hours) * hours
Expand All @@ -154,14 +159,21 @@ export class DateTime extends Time {
}

if (empty(byhour) || includes(byhour, this.hour)) break

if (this.exceedUntilOrMaxYear(until)) break
}
}

private exceedUntilOrMaxYear(until?: Date): boolean {
return (until && this.getTime() > until.getTime()) || this.year > MAXYEAR
}

public addMinutes(
minutes: number,
filtered: boolean,
byhour: number[],
byminute: number[]
byminute: number[],
until?: Date
) {
if (filtered) {
// Jump to one iteration before next day
Expand All @@ -183,6 +195,8 @@ export class DateTime extends Time {
) {
break
}

if (this.exceedUntilOrMaxYear(until)) break
}
}

Expand All @@ -191,7 +205,8 @@ export class DateTime extends Time {
filtered: boolean,
byhour: number[],
byminute: number[],
bysecond: number[]
bysecond: number[],
until?: Date
) {
if (filtered) {
// Jump to one iteration before next day
Expand All @@ -217,6 +232,8 @@ export class DateTime extends Time {
) {
break
}

if (this.exceedUntilOrMaxYear(until)) break
}
}

Expand Down Expand Up @@ -246,7 +263,7 @@ export class DateTime extends Time {
}

public add(options: ParsedOptions, filtered: boolean) {
const { freq, interval, wkst, byhour, byminute, bysecond } = options
const { freq, interval, wkst, byhour, byminute, bysecond, until } = options

switch (freq) {
case Frequency.YEARLY:
Expand All @@ -258,11 +275,18 @@ export class DateTime extends Time {
case Frequency.DAILY:
return this.addDaily(interval)
case Frequency.HOURLY:
return this.addHours(interval, filtered, byhour)
return this.addHours(interval, filtered, byhour, until)
case Frequency.MINUTELY:
return this.addMinutes(interval, filtered, byhour, byminute)
return this.addMinutes(interval, filtered, byhour, byminute, until)
case Frequency.SECONDLY:
return this.addSeconds(interval, filtered, byhour, byminute, bysecond)
return this.addSeconds(
interval,
filtered,
byhour,
byminute,
bysecond,
until
)
}
}
}
92 changes: 92 additions & 0 deletions test/datetime.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import { DateTime } from '../src/datetime'
import { Frequency } from '../src'
import { ParsedOptions } from '../src/types'

describe('datetime', () => {
describe('DateTime', () => {
const defaultOption: ParsedOptions = {
freq: Frequency.HOURLY,
dtstart: null,
interval: 1,
wkst: 0,
count: 1,
until: null,
tzid: null,
bysetpos: null,
bymonth: null,
bymonthday: [],
bynmonthday: [],
byyearday: null,
byweekno: null,
byweekday: null,
bynweekday: null,
byhour: [0],
byminute: [0],
bysecond: [0],
byeaster: null,
}

it('should not hang when add HOURLY with odd "byhour" and even "interval"', () => {
const byhour = [1]
const interval = 2
const dtstart = new Date(2024, 2, 26)
const until = new Date(2024, 2, 27)
const dt = DateTime.fromDate(dtstart)
dt.add(
{
...defaultOption,
byhour,
interval,
freq: Frequency.HOURLY,
dtstart,
until,
},
false
)

expect(dt.getTime()).toBeGreaterThan(until.getTime())
})

it('should not hang when add MINUTELY with odd "byminute" and even "interval"', () => {
const byminute = [1]
const interval = 2
const dtstart = new Date(2024, 2, 26)
const until = new Date(2024, 2, 27)
const dt = DateTime.fromDate(dtstart)
dt.add(
{
...defaultOption,
byminute,
interval,
freq: Frequency.MINUTELY,
dtstart,
until,
},
false
)

expect(dt.getTime()).toBeGreaterThan(until.getTime())
})

it('should not hang when add SECONDLY with odd "byminute" and even "interval"', () => {
const bysecond = [1]
const interval = 2
const dtstart = new Date(2024, 2, 26)
const until = new Date(2024, 2, 27)
const dt = DateTime.fromDate(dtstart)
dt.add(
{
...defaultOption,
bysecond,
interval,
freq: Frequency.SECONDLY,
dtstart,
until,
},
false
)

expect(dt.getTime()).toBeGreaterThan(until.getTime())
})
})
})

0 comments on commit 4a3a7d5

Please sign in to comment.