datetimetimezonemomentjsmoment-timezone

moment.js not taking UTC timezone


I'm using moment.js to convert the time to different timezone, but the time it is taking intially is not being treated as UTC even after specifying it.

moment.utc(dateMillis).tz(timezone).format(dateFormat);

Here, moment.utc(dateMillis) should treat dateMillis as UTC but it is not. When I pass 'GMT' to .tz(timezone), it converts the date to date-5:30, which means dateMillis is taken in IST timezone. (I'm in IST timezone), same thing happens if someone opens that page in other timezone and then switch to UTC, it will do -TZ.

I want the moment to consider the dateMillis as UTC always and then i would like to convert to desired timezone.

Adding an example:

format = 'YYYY/MM/DD HH:mm:ss (Z)'
DateMillis = Date.parse(data)

when

data = 2020-05-15 15:33:39
dateMillis = 1589537019000
timezone = 'GMT'

to convert into GMT, which means no change in value is giving me -5:30 result.

result: 2020/05/15 10:03:39 (+00:00)

Solution

  • When you call Date.parse, you're passing a string that is interpreted as local time. In other words, since your local time zone is IST (UTC+05:30), then Date.parse('2020-05-15 15:33:39') is equivalent to Date.parse('2020-05-15T15:33:39+05:30').

    The corresponding UTC time is indeed 2020-05-15T10:03:39Z, having the Unix timestamp 1589537019000 that you gave.

    You can see this even without Moment:

    const t1 = Date.parse('2020-05-15 15:33:39');
    const t2 = Date.parse('2020-05-15T15:33:39+05:30');
    const t3 = Date.parse('2020-05-15T10:03:39Z');
    console.log('t1', t1);
    console.log('t2', t2);
    console.log('t3', t3);
    console.log('t1 === t2', t1 === t2); // true only if you're in IST
    console.log('t2 === t3', t2 === t3); // always true

    Moment is doing the right thing as well. However, you've got a bit of redundant code. You can remove the tz call - moment-timezone is not needed when working only with UTC and local time.

    moment.utc(dateMillis).format(dateFormat);
    

    This creates a Moment object in UTC mode, given the Unix timestamp supplied by dateMillis. Then it emits a string in the desired format - in terms of UTC because the Moment object was in UTC mode. (Note that Unix timestamps are always in terms of UTC.)

    Thus, the source of your issue is that you are initially interpreting the input string in terms of local time. If what you actually wanted was to interpret the input string in terms of UTC, then you would do the following instead:

    moment.utc(data).format(dateFormat)
    

    Or if you just want to get the timestamp without using Moment...

    Date.parse(data.replace(' ', 'T') + 'Z')
    

    Also note that Moment is no longer recommended for new projects.