Skip to content

Commit

Permalink
fix method Dora.from under DST (#34)
Browse files Browse the repository at this point in the history
* fix method Dora.from under DST

* fix tests
  • Loading branch information
isatiso authored Nov 12, 2023
1 parent 704e9c0 commit e9687f9
Show file tree
Hide file tree
Showing 6 changed files with 93 additions and 19 deletions.
14 changes: 7 additions & 7 deletions modules/schedule/src/builtin/task-context.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,23 +19,23 @@ describe('task-context.ts', function() {
describe('#from()', function() {

it('should create instance of TaskContext', function() {
const res = TaskContext.from({ id: 'bullet-1', unit: {} as TaskUnit, execution: Dora.from([2022, 6, 1, 13, 24, 56], 'Asia/Shanghai') } as Bullet)
const res = TaskContext.from({ id: 'bullet-1', unit: {} as TaskUnit, execution: Dora.from([2022, 6, 1, 13, 24, 56], { timezone: 'Asia/Shanghai' }) } as Bullet)
expect(res).to.be.instanceof(TaskContext)
})
})

describe('.count', function() {

it('should return count of context', function() {
const res = TaskContext.from({ id: 'bullet-1', unit: {} as TaskUnit, execution: Dora.from([2022, 6, 1, 13, 24, 56], 'Asia/Shanghai') } as Bullet)
const res = TaskContext.from({ id: 'bullet-1', unit: {} as TaskUnit, execution: Dora.from([2022, 6, 1, 13, 24, 56], { timezone: 'Asia/Shanghai' }) } as Bullet)
expect(res.count).to.equal(0)
})
})

describe('.incr()', function() {

it('should increase count of context and return it', function() {
const res = TaskContext.from({ id: 'bullet-1', unit: {} as TaskUnit, execution: Dora.from([2022, 6, 1, 13, 24, 56], 'Asia/Shanghai') } as Bullet)
const res = TaskContext.from({ id: 'bullet-1', unit: {} as TaskUnit, execution: Dora.from([2022, 6, 1, 13, 24, 56], { timezone: 'Asia/Shanghai' }) } as Bullet)
expect(res.count).to.equal(0)
expect(res.incr()).to.equal(1)
expect(res.count).to.equal(1)
Expand All @@ -47,15 +47,15 @@ describe('task-context.ts', function() {
describe('.retry_limit', function() {

it('should return retry_limit of context', function() {
const res = TaskContext.from({ id: 'bullet-1', unit: {} as TaskUnit, execution: Dora.from([2022, 6, 1, 13, 24, 56], 'Asia/Shanghai') } as Bullet)
const res = TaskContext.from({ id: 'bullet-1', unit: {} as TaskUnit, execution: Dora.from([2022, 6, 1, 13, 24, 56], { timezone: 'Asia/Shanghai' }) } as Bullet)
expect(res.retry_limit).to.equal(0)
})
})

describe('.set_retry_limit()', function() {

it('should set retry limit only once', function() {
const res = TaskContext.from({ id: 'bullet-1', unit: {} as TaskUnit, execution: Dora.from([2022, 6, 1, 13, 24, 56], 'Asia/Shanghai') } as Bullet)
const res = TaskContext.from({ id: 'bullet-1', unit: {} as TaskUnit, execution: Dora.from([2022, 6, 1, 13, 24, 56], { timezone: 'Asia/Shanghai' }) } as Bullet)
expect(res.retry_limit).to.equal(0)
res.set_retry_limit(3)
expect(res.retry_limit).to.equal(3)
Expand All @@ -72,7 +72,7 @@ describe('task-context.ts', function() {
const res = TaskContext.from({
id: 'bullet-1', unit: {
crontab_str: '15 6 * * *'
} as TaskUnit, execution: Dora.from([2022, 6, 1, 13, 24, 56], 'Asia/Shanghai')
} as TaskUnit, execution: Dora.from([2022, 6, 1, 13, 24, 56], { timezone: 'Asia/Shanghai' })
} as Bullet)
expect(res.crontab).to.equal('15 6 * * *')
})
Expand All @@ -81,7 +81,7 @@ describe('task-context.ts', function() {
describe('.set() .get()', function() {

it('should set value to context', function() {
const res = TaskContext.from<{ k: string }>({ id: 'bullet-1', unit: {} as TaskUnit, execution: Dora.from([2022, 6, 1, 13, 24, 56], 'Asia/Shanghai') } as Bullet)
const res = TaskContext.from<{ k: string }>({ id: 'bullet-1', unit: {} as TaskUnit, execution: Dora.from([2022, 6, 1, 13, 24, 56], { timezone: 'Asia/Shanghai' }) } as Bullet)
res.set('k', '123')
expect(res.get('k')).to.equal('123')
})
Expand Down
2 changes: 1 addition & 1 deletion modules/schedule/src/services/schedule-hooks.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ describe('schedule-hooks.ts', function() {
const context = TaskContext.from<{ process_start: number }>({
id: 'bullet-1',
unit: { task_name: 'task name whatever some' } as TaskUnit,
execution: Dora.from([2022, 6, 1, 13, 24, 56], 'Asia/Shanghai')
execution: Dora.from([2022, 6, 1, 13, 24, 56], { timezone: 'Asia/Shanghai' })
} as Bullet)
const spy_get = chai.spy.on(context, 'get')
const spy_set = chai.spy.on(context, 'set')
Expand Down
8 changes: 4 additions & 4 deletions packages/cron/src/cron.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ export class Cron {
private parsed: ParsedFields & ParsedSpecials,
private options?: ParseCronOptions,
) {
this._utc = options?.utc ?? false
this._tz = this._utc ? 'UTC' : options?.tz ?? Dora.guess_timezone()
this._utc = this.options?.utc ?? false
this._tz = this._utc ? 'UTC' : this.options?.tz ?? Dora.guess_timezone()
this._now = Dora.now(this._tz)
this._year = this._now.year()
this._month = this._now.month() + 1
Expand Down Expand Up @@ -128,10 +128,10 @@ export class Cron {
private _make_schedule(): MonthlySchedule {
const days = new Set<number>()
if (!this.parsed.day_of_month_wildcard || this.parsed.day_of_week_wildcard) {
this._deal_special_day_of_month(days, Dora.from([this._year, this._month - 1], this._tz))
this._deal_special_day_of_month(days, Dora.from([this._year, this._month - 1], { timezone: this._tz }))
}
if (!this.parsed.day_of_week_wildcard) {
this._deal_special_day_of_week(days, Dora.from([this._year, this._month - 1], this._tz))
this._deal_special_day_of_week(days, Dora.from([this._year, this._month - 1], { timezone: this._tz }))
}
return new MonthlySchedule(this._year, this._month - 1, this._now, this._tz, [
Array.from(days).sort((a, b) => a - b),
Expand Down
2 changes: 1 addition & 1 deletion packages/cron/src/monthly-schedule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export class MonthlySchedule implements Schedule {

next() {
if (this._has_next && this._current) {
const date = Dora.from([this._year, this._month, ...this._current], this._tz)
const date = Dora.from([this._year, this._month, ...this._current], { timezone: this._tz })
this._current = this._tick()
return date
} else {
Expand Down
60 changes: 56 additions & 4 deletions packages/dora/src/dora.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,17 +40,69 @@ describe('dora.ts', function() {
describe('#from()', function() {

it('should return Dora as DateTimeArray specified', function() {
const time_arr: DateTimeArray = [2020, 9, 8, 14, 32, 1, 332]
const m = Dora.from(time_arr, 'Asia/Shanghai')
const time_arr: DateTimeArray = [2020, 7, 8, 14, 32, 1, 332]
const m = Dora.from(time_arr)
expect(m.year()).to.equal(2020)
expect(m.month()).to.equal(9)
expect(m.month()).to.equal(7)
expect(m.date()).to.equal(8)
expect(m.day()).to.equal(4)
expect(m.day()).to.equal(6)
expect(m.hour()).to.equal(14)
expect(m.minute()).to.equal(32)
expect(m.second()).to.equal(1)
expect(m.millisecond()).to.equal(332)
})

it('should deal with time when Standard time switch to DST case 1', function() {
const time_arr: DateTimeArray = [2023, 2, 12, 2, 32]
expect(() => Dora.from(time_arr, { timezone: 'America/New_York', strict: true })).to.throw()
expect(Dora.from(time_arr, { timezone: 'America/New_York' })).to.be.instanceof(Dora)
})

it('should deal with time when Standard time switch to DST case 2', function() {
const time_arr: DateTimeArray = [2023, 9, 1, 2, 26]
expect(() => Dora.from(time_arr, { timezone: 'Australia/Lord_Howe', strict: true })).to.throw()
expect(Dora.from(time_arr, { timezone: 'Australia/Lord_Howe' })).to.be.instanceof(Dora)
})

it('should deal with time when DST switch to Standard time switch case 1', function() {
const time_arr: DateTimeArray = [2023, 10, 5, 2, 26]
const m = Dora.from(time_arr, { timezone: 'America/New_York' })
expect(m.year()).to.equal(2023)
expect(m.month()).to.equal(10)
expect(m.date()).to.equal(5)
expect(m.hour()).to.equal(2)
expect(m.minute()).to.equal(26)
})

it('should deal with time when DST switch to Standard time switch case 2', function() {
const time_arr: DateTimeArray = [2023, 3, 2, 1, 36]
const m = Dora.from(time_arr, { timezone: 'Australia/Lord_Howe' })
expect(m.year()).to.equal(2023)
expect(m.month()).to.equal(3)
expect(m.date()).to.equal(2)
expect(m.hour()).to.equal(1)
expect(m.minute()).to.equal(36)
})

it('should deal with time DST time case 1', function() {
const time_arr: DateTimeArray = [2023, 11, 1, 2, 26]
const m = Dora.from(time_arr, { timezone: 'Australia/Lord_Howe' })
expect(m.year()).to.equal(2023)
expect(m.month()).to.equal(11)
expect(m.date()).to.equal(1)
expect(m.hour()).to.equal(2)
expect(m.minute()).to.equal(26)
})

it('should deal with time DST time case 2', function() {
const time_arr: DateTimeArray = [2023, 5, 1, 2, 26]
const m = Dora.from(time_arr, { timezone: 'America/New_York' })
expect(m.year()).to.equal(2023)
expect(m.month()).to.equal(5)
expect(m.date()).to.equal(1)
expect(m.hour()).to.equal(2)
expect(m.minute()).to.equal(26)
})
})

describe('#parse()', function() {
Expand Down
26 changes: 24 additions & 2 deletions packages/dora/src/dora.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,30 @@ export class Dora {
return new Dora(Date.now(), timezone)
}

static from(date_arr: DateTimeArray, timezone?: string) {
return new Dora(Date.UTC(...date_arr), timezone).dial_utc_offset()
static from(date_arr: DateTimeArray, options?: { timezone?: string, strict?: boolean }) {
const timezone = options?.timezone
const strict_mode = options?.strict ?? false
const utc = Date.UTC(...date_arr)
const utc_date = new Date(utc)
const last_offset = new Dora(utc - 24 * 60 * 60 * 1000, timezone).utc_offset()
const next_offset = new Dora(utc + 24 * 60 * 60 * 1000, timezone).utc_offset()
if (last_offset === next_offset) {
return new Dora(Date.UTC(...date_arr), timezone).add(last_offset, 'minute')
} else {
const d_with_last_offset = new Dora(Date.UTC(...date_arr), timezone).add(last_offset, 'minute')
const d_with_next_offset = new Dora(Date.UTC(...date_arr), timezone).add(next_offset, 'minute')
if (d_with_last_offset.hour() === utc_date.getUTCHours() && d_with_last_offset.minute() === utc_date.getUTCMinutes()) {
return d_with_last_offset
} else if (d_with_next_offset.hour() === utc_date.getUTCHours() && d_with_next_offset.minute() === utc_date.getUTCMinutes()) {
return new Dora(Date.UTC(...date_arr), timezone).add(next_offset, 'minute')
} else {
if (strict_mode) {
throw new Error(`Invalid date: ${date_arr}, under timezone ${timezone}`)
} else {
return new Dora(Date.UTC(...date_arr), timezone).dial_utc_offset()
}
}
}
}

static parse(date_str: string) {
Expand Down

0 comments on commit e9687f9

Please sign in to comment.