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

Daylight savings? #157

Open
robinsongz opened this issue Mar 11, 2019 · 23 comments
Open

Daylight savings? #157

robinsongz opened this issue Mar 11, 2019 · 23 comments

Comments

@robinsongz
Copy link

Is node-cron updated for daylight savings? When I put timezone America/Los_Angeles, it is still going off pre-daylight savings times.

@vwbusguy
Copy link

I have the same issue here using {scheduled: true, timezone: "America/Los_Angeles"}

@vwbusguy
Copy link

The timezone offset is hard-coded in the supporting library, so it doesn't support DST: https://github.com/node-cron/tz-offset/blob/master/generated/offsets.json

@thehappycoder
Copy link

Glad I checked this before using this node package :)

@ndelanou
Copy link

ndelanou commented Apr 3, 2019

Same problem here with timezone 'Europe/Paris'

@vwbusguy
Copy link

vwbusguy commented Apr 8, 2019

It will be a problem anywhere that does DST the way this is implemented. The offset is hard-coded.

@jaclarke
Copy link

Instead of a hard-coded list of offsets, there's the way Luxon handles it using the Intl.DateTimeFormat api (https://moment.github.io/luxon/docs/manual/zones.html#iana-support). However this would mean only supporting modern browsers / node 8+ without a polyfill (https://moment.github.io/luxon/docs/manual/matrix.html).

@vwbusguy
Copy link

The problem is here - node-cron/tz-offset#8

@Arlen22
Copy link

Arlen22 commented May 23, 2019

Servers normally run UTC anyway, so the offset is just helpful. Besides, you wouldn't want the mess of making sure tasks don't duplicate on the night DST starts or ends. But maybe some one else has some examples of how it could be helpful. I guess it depends on what people use it for and it could be made optional.

@jaclarke
Copy link

As I understand it, a js Date object doesn't really have a timezone/offset associated with it anyway, it just stores the date as a number of milliseconds since the 1st Jan 1970 epoch, so is effectively using UTC internally.
The problem is getting that timestamp into a second, minute, hour, day, month, year format for matching to the cron expression correctly in the users local time, accounting for their local offset and DST, since the getMinutes(), getHours(), etc. methods work in the systems local time, so for most servers with UTC system time they return the same as the getUTCMinutes(), getUTCHours() methods. This is where tz-offset library returning the correct offsets for DST is needed.

I think you're right that it does depend on what the cron expression is. For something like "0 * * * *" where the task just runs every hour the offset doesn't matter, but for tasks that run for example once a day at a specific time (eg "0 9 * * *"), you probably want it to run in the users local time, eg. for a user in the America/Los_Angeles timezone, 9:00 local time should be scheduled at 17:00 UTC (or 16:00 UTC during DST) on the server.

As for handling the weird missing or repeated hour when DST starts or ends, here's how its handled it in cronosjs, which handles it by adding and subtracting an hour from the date in UTC, and comparing how many hours are actually offset in local time to detect the missing/repeating hours and adjusting the date accordingly.

@Arlen22
Copy link

Arlen22 commented May 23, 2019

It would definitely need to explicitly enabled because cron is used all over the server world for stuff.

@JulienStitelet
Copy link

Is moment-timezone.js too big for you as a dep ?

@korydondzila
Copy link

I recently started using node-cron for a project and I have this as my schedule

cron.schedule('5 * 0-1,5-23 * * *', job, { timezone: "America/New_York" });

This should have the cron run on the 5th second of every minute from 5am to 1am in EST, which observes DST.

The issue is that during DST, because node-cron doesn't observe it or have a way to enable it, the job runs from 6am to 2am.

The easiest fix for me is to just have to run constantly and not during a specific range of hours, but this isn't preferred. The server runs UTC, but the time range required is tied to real world event that runs from 5am to 1am, so I think this is a specific example where DST support is needed.

@JulienStitelet
Copy link

I personally changed to 'cron' package. Where timezone and DST works as expected.

@willtalmadge
Copy link

I personally changed to 'cron' package. Where timezone and DST works as expected.

I personally just moved from 'cron' due to this issue kelektiv/node-cron#315 and ran into this issue. I'm just going to have to use the real cron. It seems like none of the cron modules for node work.

@vwbusguy
Copy link

In fairness, willtalmadge, it works about as well as most nodejs libraries do. It fit the specific use case for the person who made it and now the rest of us are trying to figure out how to workaround that implementation. Unless someone is willing to fork this code and maintain it, we're stuck with remembering to patch and release our code that depends on this every time daylight savings changes happen.

@jaclarke
Copy link

I've submitted a pull request to the node-cron/tz-offset library that this one depends on, to handle DST changes correctly using the Intl.DateTimeFormat api. Though since it does depend on the Intl.DateTimeFormat api, it does mean it will only work on newer browser/node versions, so the maintainer may not want to merge it if they still require support for older browsers.

Alternatively, if you don't mind only having support for newer browsers/node versions, I've also published the cron library (cronosjs) that I wrote when I ran into the DST problem using this library (also because I needed to be able to get the next date the cron expression matched), which I'm happy to maintain. (As a bonus it handles some extended cron syntax and has configurable handling of the missing/repeated hours that come with DST starting/ending)

@willtalmadge
Copy link

In fairness, willtalmadge, it works about as well as most nodejs libraries do. It fit the specific use case for the person who made it and now the rest of us are trying to figure out how to workaround that implementation. Unless someone is willing to fork this code and maintain it, we're stuck with remembering to patch and release our code that depends on this every time daylight savings changes happen.

You are right, I was overly harsh out of frustration.

@jgillick
Copy link

Looks like this might have been resolved with #248 in version 3.0.0.

@likhit-vivek
Copy link

likhit-vivek commented Apr 11, 2023

I recently started using node-cron for a project and I have this as my schedule

cron.schedule('5 * 0-1,5-23 * * *', job, { timezone: "America/New_York" });

This should have the cron run on the 5th second of every minute from 5am to 1am in EST, which observes DST.

The issue is that during DST, because node-cron doesn't observe it or have a way to enable it, the job runs from 6am to 2am.

The easiest fix for me is to just have to run constantly and not during a specific range of hours, but this isn't preferred. The server runs UTC, but the time range required is tied to real world event that runs from 5am to 1am, so I think this is a specific example where DST support is needed.

I was stuck with a similar issue and found a simpler workaround using dayjs, which can account for daylight savings on its own.
I feel using multiple schedules as shown below could be sufficient for most cases where DST support is needed.

Schedule the job thrice:

  1. cron.schedule('5 * 4 * * *', job, { timezone: "America/New_York" });
    This runs at 5 am when DST is on, at 4 am when DST is off
  2. cron.schedule('5 * 0,5-23 * * *', job, { timezone: "America/New_York" });
    This runs from 6am to 1 am when DST is on, from 5 am to 12 am when DST is off
  3. cron.schedule('5 * 1 * * *', job, { timezone: "America/New_York" });
    This runs at 1 am when DST is off, at 2 am when DST is on

Inside the job function, use dayjs to run the job only when needed:

function job() {
    const curr_time = dayjs();
    const curr_time_ny = curr_time.tz("America/New_York");
    const curr_hour_ny = curr_time_ny.hour();
    if (curr_hour_ny <=1 || curr_hour_ny>=5) { /* execute the job */ }
}

Now the job runs from 5 am to 1 am throughout the year cuz the above if condition prevents execution at 4 am when DST is off (as in schedule 1 above) and at 2 am when DST is on (as in schedule 3 above).

@absorpheus
Copy link

absorpheus commented Apr 13, 2023

I upgraded node-schedule to version 2.0.0 and can confirm that timezones are now working correctly (tested the timezone 'America/New_York' on AWS ECS which had a default timezone set to UTC.

@tanosaur
Copy link

tanosaur commented Apr 28, 2023

It's not working for me - now that it's entered British Summer Time all the jobs I set are happening 1 hour later than expected. I'm using node-cron version 3.0.2

@elgiano
Copy link

elgiano commented Aug 29, 2023

Timezones and daylight savings work for me too.
Running node-cron 3.0.2, on a server with UTC, a cronjob scheduled every day at 9am on Copenhagen timezone, runs correctly at 9am during copenhagen's summer time.

@elgiano
Copy link

elgiano commented Aug 30, 2023

However, there is a memory leak when using timezone: #358

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