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

Tasks missed or repeated if system time observes daylight savings #174

Open
jaclarke opened this issue May 23, 2019 · 0 comments
Open

Tasks missed or repeated if system time observes daylight savings #174

jaclarke opened this issue May 23, 2019 · 0 comments

Comments

@jaclarke
Copy link

jaclarke commented May 23, 2019

The issue seems be be that tz-offset lib tries to apply the offset for a timezone in the local system time, and node-cron then gets the minute, hour, day, etc. in the local system time with getHours() etc. so tasks get missed or repeated when the hour doesn't exist or is repeated in the system local time.

https://github.com/node-cron/tz-offset/blob/50f2e1cde8447b332215a5deee09127cd30088eb/src/tz-offset.js#L15-L24

match(date){
if(this.timezone){
date = tzOffset.timeAt(date, this.timezone);
}
var runOnSecond = matchPattern(this.expressions[0], date.getSeconds());
var runOnMinute = matchPattern(this.expressions[1], date.getMinutes());
var runOnHour = matchPattern(this.expressions[2], date.getHours());
var runOnDay = matchPattern(this.expressions[3], date.getDate());
var runOnMonth = matchPattern(this.expressions[4], date.getMonth() + 1);
var runOnWeekDay = matchPattern(this.expressions[5], date.getDay());
return runOnSecond && runOnMinute && runOnHour && runOnDay && runOnMonth && runOnWeekDay;
}

For example if the system timezone is "Europe/London" which observes DST, scheduling tasks in another timezone (for example "Asia/Tokyo", which doesn't observe DST, so unrelated to #157):

const tzoffset = require('tz-offset'); // tz-offset@0.0.2

const date0 = new Date('2019-03-30T23:30:00.000Z');
const date1 = new Date('2019-03-31T00:30:00.000Z');
const date2 = new Date('2019-03-31T01:30:00.000Z');
const date3 = new Date('2019-03-31T02:30:00.000Z');

const date4 = new Date('2019-10-26T23:30:00.000Z');
const date5 = new Date('2019-10-27T00:30:00.000Z');
const date6 = new Date('2019-10-27T01:30:00.000Z');
const date7 = new Date('2019-10-27T02:30:00.000Z');

const date0Tokyo = tzoffset.timeAt(date0, 'Asia/Tokyo');
const date1Tokyo = tzoffset.timeAt(date1, 'Asia/Tokyo');
const date2Tokyo = tzoffset.timeAt(date2, 'Asia/Tokyo');
const date3Tokyo = tzoffset.timeAt(date3, 'Asia/Tokyo');

const date4Tokyo = tzoffset.timeAt(date4, 'Asia/Tokyo');
const date5Tokyo = tzoffset.timeAt(date5, 'Asia/Tokyo');
const date6Tokyo = tzoffset.timeAt(date6, 'Asia/Tokyo');
const date7Tokyo = tzoffset.timeAt(date7, 'Asia/Tokyo');

const printLocalTime = date => console.log(`(system local time) hour: ${date.getHours()}, minute: ${date.getMinutes()}, second: ${date.getSeconds()}`)

printLocalTime(date0Tokyo); // (system local time) hour: 9, minute: 30, second: 0
printLocalTime(date1Tokyo); // (system local time) hour: 10, minute: 30, second: 0
printLocalTime(date2Tokyo); // (system local time) hour: 10, minute: 30, second: 0
printLocalTime(date3Tokyo); // (system local time) hour: 11, minute: 30, second: 0

printLocalTime(date4Tokyo); // (system local time) hour: 7, minute: 30, second: 0
printLocalTime(date5Tokyo); // (system local time) hour: 8, minute: 30, second: 0
printLocalTime(date6Tokyo); // (system local time) hour: 10, minute: 30, second: 0
printLocalTime(date7Tokyo); // (system local time) hour: 11, minute: 30, second: 0

Changing timeAt to apply the offset in UTC time:

const timeAt = (date, timezone) => {
    const timeUtc = date.getTime();
    const offset = offsetOf(timezone) * -60000;
    return new Date(timeUtc + offset);
};

and time-matcher.js to use getUTCHours() etc. seems to fix the issue:

const printUTCTime = date => console.log(`(UTC time) hour: ${date.getUTCHours()}, minute: ${date.getUTCMinutes()}, second: ${date.getUTCSeconds()}`)

printUTCTime(date0Tokyo); // (UTC time) hour: 8, minute: 30, second: 0
printUTCTime(date1Tokyo); // (UTC time) hour: 9, minute: 30, second: 0
printUTCTime(date2Tokyo); // (UTC time) hour: 10, minute: 30, second: 0
printUTCTime(date3Tokyo); // (UTC time) hour: 11, minute: 30, second: 0

printUTCTime(date4Tokyo); // (UTC time) hour: 8, minute: 30, second: 0
printUTCTime(date5Tokyo); // (UTC time) hour: 9, minute: 30, second: 0
printUTCTime(date6Tokyo); // (UTC time) hour: 10, minute: 30, second: 0
printUTCTime(date7Tokyo); // (UTC time) hour: 11, minute: 30, second: 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant