Search code examples
javascriptdatetimemomentjsunix-timestamp

How to obtain unix timestamps for same date in 2 different time zones with moment.js?


I'm working on an app where users can choose what time zone they are recording time in. But internally, I want to store the time as a unix timestamp.

Say I have a date '2016-01-01 1:00 pm'. If I store this date in CDT (America/Chicago), it is my understanding that the resulting unix time stamp should be different than had I stored the same date in MDT (America/Denver). However, I get the same unix time stamp for both dates, and I'm having trouble understanding why.

var chicagoDate = moment('2016-01-01 1:00 pm').tz('America/Chicago');
var denverDate = moment('2016-01-01 1:00 pm').tz('America/Denver');

chicagoDate.format();
// "2016-01-01T07:00:00-06:00"
denverDate.format();
// "2016-01-01T06:00:00-07:00"

So far this confirms that the 2 dates are distinct from one another as shown by their UTC representation obtained by using format(). But here is where I'm getting confused:

chicagoDate.unix();
// 1451653200
denverDate.unix();
// 1451653200

Shouldn't 2 distinct UTC dates result in 2 distinct unix timestamps?


Solution

  • In:

    moment('2016-01-01 1:00 pm').tz('America/Chicago');
    

    there is no parse format parameter, so moment.js looks to see if the format is one that it can parse without the format. It can't, so it falls back to the built–in parser as if you'd written:

    moment(new Date('2016-01-01 1:00 pm')).tz('America/Chicago');
    

    And puts warning in the console:

    Deprecation warning: value provided is not in a recognized RFC2822 or ISO format. moment construction falls back to js Date(), which is not reliable across all browsers and versions…

    Safari at least parses it as an invalid date (timestamp), so you should include the parse format:

    moment(new Date('2016-01-01 1:00 pm', 'YYYY-MM-DD h:mm a')).tz('America/Chicago');
    

    Secondly, the string is parsed as local since there is no timezone associated with the timestamp. So both lines of code produce exactly the same time value (i.e. offset from the epoch) and the two Dates produced are effectively identical.

    The call to tz sets the timezone to use for all subsequent operations, so the output shows different times because different offsets have been applied at the formatting stage. The actual Dates being formatted are still effectively identical.

    If you want the string to be parsed as for another timezone, you need to either manually include it in the string at the parse stage (e.g. '-06:00' or whatever), or use a library like Luxon with an IANA location (e.g. 'America/Chicago').