Javascript Date - how to know whether DST is in effect in a given timezone

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?

Since you said you have the tzid, I recommend you use TimeZoneJS. This is a JavaScript implementation of the IANA/Olson timezone database.

First, you need to initialize the library:

timezoneJS.timezone.zoneFileBasePath = 'scripts/tz';
timezoneJS.timezone.init({ async: false });

The scripts/tz path is where I have placed the tzdb data files.

I set async: false because I'm using it with jQuery. If you want, you can use the Fleegix.js library instead - but I prefer to stick with jQuery. I was testing in a web browser - the setup may be slightly different from Node.

Once it's setup, you then establish a timezoneJS.Date object. Since you said you had ticks (of seconds) and a tzid, you would do it like this:

var ticks = secondsSinceEpoch * 1000; // you need ticks in milliseconds
var dt = new timezoneJS.Date(ticks, tzid);  // pass a tzid like 'America/New_York'

Then you can get the abbreviation of the timezone in effect:

var abbreviation = dt.getTimezoneAbbreviation(); // for example, EST or EDT

Or you can get the UTC offset in effect:

var offset = dt.getTimezoneOffset();  // returns whole minutes as a GMT offset (opposite sign of UTC)

This is a cleaner way to get a UTC offset string:

var offset = -dt.getTimezoneOffset();
var offsetString = (offset < 0 ? '-' : '+') + zeroPad(Math.abs(offset / 60), 2) + ':' + zeroPad(Math.abs(offset % 60), 2);

I'm using the following zeroPad function, but you can use whatever you like:

function zeroPad(num, places) {
    var zero = places - num.toString().length + 1;
    return Array(+(zero > 0 && zero)).join("0") + num;
}

Now that you have an offset and abbreviation (either -04:00 for EDT or -05:00 for EST) you will need to determine if this is "daylight time" or "summer time" on your own. Unfortunately, it's not a simple as checking a boolean, or checking the middle character of the abbreviation (the "S" could stand for "Standard" or "Summer", and some abbreviations are more than 3 characters).

If you already know which offset is standard and which is daylight for the data you have, then you are done. If not, you would need some other way to identify this. There is a list here that may help, but keep in mind that the abbreviation alone is not good for a lookup since it could refer to many different time zones.

In practice, it may not be all that important to know which offset is daylight/summer vs the standard one, as long as you display it correctly.

Also to note - while I was testing this out, I found what appears to be a bug in the TimezoneJS library that caused some of the results to be an hour off when in EDT. I have logged this with the TimezoneJS authors, and will update here when I hear back. If anyone knows of a different TZDB implementation in Javascript, please let me know in comments. Thanks.

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.

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();