diff --git a/lib/time.js b/lib/time.js index b236ac94..ca3654cb 100644 --- a/lib/time.js +++ b/lib/time.js @@ -152,17 +152,27 @@ function CronTime(luxon) { } if (typeof this.utcOffset !== 'undefined') { - let offset = - this.utcOffset >= 60 || this.utcOffset <= -60 - ? this.utcOffset / 60 - : this.utcOffset; + if (typeof this.utcOffset === 'string') { + const parts = this.utcOffset.split(':'); + const hours = parseInt(parts[0]); + const minutes = parseInt(parts[1]); + if (this.utcOffset[0] === '-') this.utcOffset = hours * 60 - minutes; + else this.utcOffset = hours * 60 + minutes; + } + let offset = this.utcOffset / 60; + offset = parseInt(offset); + const remainderMins = Math.abs(this.utcOffset - offset * 60); + const remainderMinsString = + remainderMins >= 10 ? remainderMins : '0' + remainderMins; + let utcZone = 'UTC'; - if (offset < 0) { - utcZone += offset; - } else if (offset > 0) { - utcZone += `+${offset}`; + + if (this.utcOffset < 0) { + utcZone += `${offset === 0 ? '-0' : offset}:${remainderMinsString}`; + } else { + utcZone += `+${offset}:${remainderMinsString}`; } date = date.setZone(utcZone); diff --git a/tests/cron.test.js b/tests/cron.test.js index 4d515e38..ed041d5a 100644 --- a/tests/cron.test.js +++ b/tests/cron.test.js @@ -799,6 +799,39 @@ describe('cron', () => { expect(callback).toHaveBeenCalledTimes(1); }); + it('should run a job using cron syntax with numeric format utcOffset with minute', () => { + const clock = sinon.useFakeTimers(); + const callback = jest.fn(); + + const luxon = require('luxon'); + // Current time + const t = luxon.DateTime.local(); + // UTC Offset decreased by 45 minutes + const utcOffset = t.offset - 45; + + const job = new cron.CronJob( + t.second + ' ' + t.minute + ' ' + t.hour + ' * * *', + callback, + null, + true, + null, + null, + null, + utcOffset + ); + // tick to 1s before 45 minutes + clock.tick(1000 * 60 * 45 - 1000); + expect(callback).toHaveBeenCalledTimes(0); + + //tick 1s + clock.tick(1000); + expect(callback).toHaveBeenCalledTimes(1); + + clock.restore(); + + job.stop(); + }); + it('should run a job using cron syntax with string format utcOffset', () => { const clock = sinon.useFakeTimers(); const callback = jest.fn(); @@ -834,6 +867,42 @@ describe('cron', () => { expect(callback).toHaveBeenCalledTimes(1); }); + it('should run a job using cron syntax with string format utcOffset with minute', () => { + const clock = sinon.useFakeTimers(); + const callback = jest.fn(); + const luxon = require('luxon'); + // Current time + const t = luxon.DateTime.local(); + // UTC Offset decreased by an 45 minutes (string format '(+/-)HH:mm') + const utcOffset = t.offset - 45; + let utcOffsetString = utcOffset > 0 ? '+' : '-'; + utcOffsetString += ('0' + Math.floor(Math.abs(utcOffset) / 60)).slice(-2); + utcOffsetString += ':'; + utcOffsetString += ('0' + (utcOffset % 60)).slice(-2); + + const job = new cron.CronJob( + t.second + ' ' + t.minute + ' ' + t.hour + ' * * *', + callback, + null, + true, + null, + null, + null, + utcOffset + ); + // tick to 1s before 45 minutes + clock.tick(1000 * 60 * 45 - 1000); + expect(callback).toHaveBeenCalledTimes(0); + + //tick 1s + clock.tick(1000); + expect(callback).toHaveBeenCalledTimes(1); + + clock.restore(); + + job.stop(); + }); + it('should run a job using cron syntax with number format utcOffset that is 0', () => { const clock = sinon.useFakeTimers(); const callback = jest.fn(); diff --git a/tests/crontime.test.js b/tests/crontime.test.js index 0d962d06..4d875c90 100644 --- a/tests/crontime.test.js +++ b/tests/crontime.test.js @@ -634,18 +634,6 @@ describe('crontime', () => { clock.restore(); }); - it('should accept 4 as a valid UTC offset', () => { - const clock = sinon.useFakeTimers(); - - const cronTime = new cron.CronTime('0 11 * * *', null, 5); - const expected = luxon.DateTime.local().plus({ hours: 6 }).toSeconds(); - const actual = cronTime.sendAt().toSeconds(); - - expect(actual).toEqual(expected); - - clock.restore(); - }); - it('should detect real date in the past', () => { const clock = sinon.useFakeTimers();