javascriptreact-nativeexpomomentjsmoment-timezone

Moment not giving same values


var a = moment().toISOString(true)
var b = moment();
var c = moment(b.toISOString(true));
console.log(a);// 2024-04-15T00:09:47.226+01:00 --->here time is one hour ahead
console.log(b);//"2024-04-14T23:09:47.472Z"
console.log(c);//"2024-04-14T23:09:47.472Z"

Please help me understand the following


Solution

  • 2024-04-14T12:00:00.000Z
    2024-04-14T13:00:00.000+01:00
    

    Both of those ISO strings refer to the same absolute point in time, commonly called an instant. They both correspond to a Unix time of 1713096000000.

    They differ in their timezone information. Both(!) are zoned, the first string is in UTC (fixed offset of +00:00), denoted by the Z at the end, and the second has a timezone offset of +01:00. Also of note: a timezone offset is not the same as a timezone, but that distinction is unimportant for this particular use.

    Both representations are correct regarding their absolute time. Which one is suited depends on if the timezone offset is relevant to your application's needs. If you're only concerned about the absolute time (for example, if you only want to display "created 10min ago"), then either is fine.

    Sometimes the offset is relevant, for example if you want to show something like "Employee logged in at 8am", it should be in the respective local time of that employee. Considering the employee is at +01:00 and you're at -05:00, it would either say "Employee logged in at 9am" if converted to UTC and displayed in UTC, or if displayed as your local time "Employee logged in at 2pm".

    There are also dates that aren't associated with any timezone offset. They're called plain dates. A good example would be a birthday, because showing 2024-04-14T00:00:00.000Z as a local time at -01:00 would give the wrong date of 2024-04-13.

    Important: A plain date can't be mapped to an absolute time without knowing the timezone offset. In the employee login example, if you only wanted to display that message, you could use a plain date (created in the employees local timezone) but it would be incorrect to use for other use cases such as "Employee logged in 3h ago", since you can't know the absolute point in time. Many date libraries will happily parse a plain date as a local date, which is generally incorrect, but will only be noticed when someone from a different timezone uses your app.

    Conclusion: Basically every time you programmatically capture a date, it should be an absolute time. Whether the offset matters and how it's treated depends on the use case.