7

First off, I am NOT looking for whether DST is in effect locally.

I'm running a Node process that has data that has associated timestamps. I need to convert those timestamps to a day/month/year in a specified time zone, but all I'm given is the time zone's offset and DST offset.

I wish Date / Moment worked better with time zones. They work great with UTC or Local time zones, but it seems you need to hack it to get something else.

Is there something I'm missing? Assuming I can determine whether DST is in effect, would this work:

var d = new Date(ts + timezone_offset - local_offset);
d.getMonth();
d.getDate();

where timezone_offset is the time zone's offset (either the standard offset or the dst one)?

How might I determine whether DST is in effect?

Matt Johnson-Pint
  • 230,703
  • 74
  • 448
  • 575
user1756980
  • 3,807
  • 4
  • 16
  • 13
  • is this a duplicate: http://stackoverflow.com/questions/4903722/working-with-timezones-and-daylight-savings-time-in-javascript?rq=1 – kmote Feb 08 '13 at 20:06
  • this is actually quite easy, you just need to do a few date comparisons, see my repo here for an extended example: https://github.com/jthoburn/Date.toString.js – runspired Feb 08 '13 at 20:16
  • specifically, look at the code for 'I' and modify it to use this method: http://stackoverflow.com/a/14636431/1883464 – runspired Feb 08 '13 at 20:21
  • Do you actually know the timezone id? If so, is it an Olson id such as "America/New_York", or a Windows id such as "Eastern Standard Time"? Or is all you know that the offset is -5 or -4? – Matt Johnson-Pint Feb 08 '13 at 20:32
  • 1
    @runspired - Please see my comments on your library [here](https://github.com/jthoburn/Date.toString.js/issues/1). Thanks. – Matt Johnson-Pint Feb 08 '13 at 21:03
  • @kmote - No it's not a dup because he's running on Node - not in the browser. Depending on his answer to my earlier comment, [TimezoneJS](https://github.com/mde/timezone-js) may actually be appropriate. I will elaborate in an answer after he responds. – Matt Johnson-Pint Feb 08 '13 at 21:11
  • @runspired - maybe I don't understand the code, but isn't it relying on the time zone being local? If not I can't see what it's doing – user1756980 Feb 08 '13 at 21:12
  • 1
    @MattJohnson I have both, "America/New_York" and gmt -5, dst -4 – user1756980 Feb 08 '13 at 21:19
  • @user1756980 How are the timestamps given to you? ISO strings? ticks? multiple values? Are they local for that timezone, or are they UTC time? Can you provide an example? I want to be sure to supply a usable answer. Thanks. – Matt Johnson-Pint Feb 08 '13 at 21:35
  • I managed to make something that I think works, I printed the output for all the days of this year and compared to when google says dst starts and ends, and it worked, I'm not sure if it will work for every year / every time (I just did midnight each day). The timestamps are ticks (seconds since epoch, but of course could easily be converted to milliseconds if need be). – user1756980 Feb 08 '13 at 21:53
  • @user1756980 That's not a good plan. The dates vary wildly for different zones, and even with the same zones they have changed year over year. I am almost done with a sample of how to do what you want using TimezoneJS, and will post shortly. – Matt Johnson-Pint Feb 09 '13 at 21:17

3 Answers3

3

First, recognize that if all you have are the offsets, you cannot solve this problem. You must have a time zone identifier, such as "America/New_York". Since in the question comments you said you do indeed have this, then you can use one of these libraries to get the job done.

I had previously posted another answer to this question, recommending TimeZoneJS, but I'll retract that now - as this question is specifically about DST, and TimeZoneJS has bugs, reporting values incorrectly near DST transitions.

Instead, I'll now recommend using moment.js with the moment-timezone add-on. Once installing both libraries (being sure to load actual time zone data, per the docs), the code is quite simple:

moment(timestamp).tz(timezone).isDST()

For example:

moment(1451624400000).tz('America/New_York').isDST(); // false
moment(1467345600000).tz('America/New_York').isDST(); // true

Or, if your timestamps are already strings in terms of the local time, then use this syntax instead:

moment.tz('2016-01-01T00:00:00','America/New_York').isDST(); // false
moment.tz('2016-07-01T00:00:00','America/New_York').isDST(); // true
Community
  • 1
  • 1
Matt Johnson-Pint
  • 230,703
  • 74
  • 448
  • 575
  • Does this library use Date object as a proxy under the hood like timezoneJS does ? Or did they implement everything from scratch ? – matf Jan 28 '16 at 17:03
  • Moment itself does currently use the `Date` object for some things, but takes into account all of the various quirks. Still, we have [an open item](https://github.com/moment/moment/issues/2617) to consider removing it. Moment-timezone implements everything from scratch with regards to time zones. It doesn't rely on the Date object to do time zone conversions. – Matt Johnson-Pint Jan 28 '16 at 17:08
  • I've tested cases where timezoneJS would fail and they are working correctly with moment-timezone. – matf Jan 28 '16 at 23:20
0

Is there something I'm missing? Assuming I can determine whether DST is in effect, would this work where timezone_offset is the requested time zone's offset?

Try to always use the UTC methods to get attributes of dates. That way your (server's) local timezone will not affect any calculations:

var d = new Date(ts + timezone_offset);
d.getUTCMonth();
d.getUTCDate();

How might I determine whether DST is in effect?

That's complicated. There are/were many different algorithms to determine DST beginning and end, depending on the region - have a look at http://en.wikipedia.org/wiki/Daylight_saving_time_by_country for example.

I don't know whether there are any libraries that have already coded these, or maybe even contact the timezone database for correct information. The last resort would be to ask the user himself for timezone details.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
0

moment.js (http://momentjs.com/) has a isDST function. You could use moment (lots simpler), or check how it is implemented.

moment(your_date).isDST();
Pascal Belloncle
  • 11,184
  • 3
  • 56
  • 56