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
27 changes: 21 additions & 6 deletions lib/time.js
Original file line number Diff line number Diff line change
Expand Up @@ -152,17 +152,32 @@ function CronTime(luxon) {
}

if (typeof this.utcOffset !== 'undefined') {
let offset =
if (typeof this.utcOffset === 'string') {
rharshit82 marked this conversation as resolved.
Show resolved Hide resolved
const parts = this.utcOffset.split(':');
const hours = parseInt(parts[0]);
const minutes = parseInt(parts[1] ? parts[1] : '0');
if (this.utcOffset[0] === '-') this.utcOffset = hours * 60 - minutes;
else this.utcOffset = hours * 60 + minutes;
}

let offsetHours =
this.utcOffset >= 60 || this.utcOffset <= -60
? this.utcOffset / 60
: this.utcOffset;
offset = parseInt(offset);

offsetHours = parseInt(offsetHours);

const offsetMins = Math.abs(this.utcOffset - offsetHours * 60);
const offsetMinsStr = offsetMins >= 10 ? offsetMins : '0' + offsetMins;
sheerlox marked this conversation as resolved.
Show resolved Hide resolved

rharshit82 marked this conversation as resolved.
Show resolved Hide resolved
let utcZone = 'UTC';
if (offset < 0) {
utcZone += offset;
} else if (offset > 0) {
utcZone += `+${offset}`;

if (this.utcOffset < 0) {
utcZone += `${
offsetHours === 0 ? '-0' : offsetHours
}:${offsetMinsStr}`;
} else {
utcZone += `+${offsetHours}:${offsetMinsStr}`;
}

date = date.setZone(utcZone);
Expand Down
75 changes: 70 additions & 5 deletions tests/cron.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,7 @@
const clock = sinon.useFakeTimers();
const callback = jest.fn();

var job = cron.job({
const job = cron.job({
cronTime: '* * * * * *',
onTick: callback,
runOnInit: true
Expand Down Expand Up @@ -799,6 +799,39 @@
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 All @@ -807,10 +840,7 @@
const t = luxon.DateTime.local();
// UTC Offset decreased by an hour (string format '(+/-)HH:mm')
const utcOffset = t.offset - 60;
let utcOffsetString = utcOffset > 0 ? '+' : '-';
utcOffsetString += ('0' + Math.floor(Math.abs(utcOffset) / 60)).slice(-2);
utcOffsetString += ':';
utcOffsetString += ('0' + (utcOffset % 60)).slice(-2);
const utcOffsetString = `${utcOffset > 0 ? '+' : '-'}${('0' + Math.floor(Math.abs(utcOffset) / 60)).slice(-2)}:${('0' + (utcOffset % 60)).slice(-2)}`;

const job = new cron.CronJob(
t.second + ' ' + t.minute + ' ' + t.hour + ' * * *',
Expand All @@ -834,11 +864,46 @@
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

Check failure on line 872 in tests/cron.test.js

View workflow job for this annotation

GitHub Actions / lint-and-test (14.x, ubuntu-latest)

Replace `'0'·+·Math.floor(Math.abs(utcOffset)·/·60)` with `⏎↹↹↹↹'0'·+·Math.floor(Math.abs(utcOffset)·/·60)⏎↹↹↹`

Check failure on line 872 in tests/cron.test.js

View workflow job for this annotation

GitHub Actions / lint-and-test (16.x, ubuntu-latest)

Replace `'0'·+·Math.floor(Math.abs(utcOffset)·/·60)` with `⏎↹↹↹↹'0'·+·Math.floor(Math.abs(utcOffset)·/·60)⏎↹↹↹`
const t = luxon.DateTime.local();
// UTC Offset decreased by 45 minutes (string format '(+/-)HH:mm')
const utcOffset = t.offset - 45;

const utcOffsetString = `${utcOffset > 0 ? '+' : '-'}${('0' + Math.floor(Math.abs(utcOffset) / 60)).slice(-2)}:${('0' + (utcOffset % 60)).slice(-2)}`;

const job = new cron.CronJob(
t.second + ' ' + t.minute + ' ' + t.hour + ' * * *',
callback,
null,
true,
null,
null,
null,
utcOffsetString
);
// 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();

const job = new cron.CronJob(

Check failure on line 906 in tests/cron.test.js

View workflow job for this annotation

GitHub Actions / lint-and-test (14.x, ubuntu-latest)

Replace `'0'·+·Math.floor(Math.abs(utcOffset)·/·60)` with `⏎↹↹↹↹'0'·+·Math.floor(Math.abs(utcOffset)·/·60)⏎↹↹↹`

Check failure on line 906 in tests/cron.test.js

View workflow job for this annotation

GitHub Actions / lint-and-test (16.x, ubuntu-latest)

Replace `'0'·+·Math.floor(Math.abs(utcOffset)·/·60)` with `⏎↹↹↹↹'0'·+·Math.floor(Math.abs(utcOffset)·/·60)⏎↹↹↹`
'* * * * * *',
callback,
null,
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
Loading