Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: added fractional offset support #685

Merged
merged 14 commits into from
Sep 25, 2023
26 changes: 18 additions & 8 deletions lib/time.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
69 changes: 69 additions & 0 deletions tests/cron.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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();
Expand Down
12 changes: 0 additions & 12 deletions tests/crontime.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand Down