0

I'm returned a set of ISO8601 dates, along with their offset. I would like to show the user the hour calculated according to that offset, not the local one. Unfortunately I don't have the timezone, in order to use the Intl interface.

An example. Imagine I'm on a etc/GMT+4. If I'm returned this:

2019-05-30T07:00:00.000+01:00

I want to show the user the following:

07:00:00

not:

10:00
Bertuz
  • 2,390
  • 3
  • 25
  • 50
  • the time according to the specified offset is `7:00` not `8:00` and for GMT+4 it would be `10:00` not `12:00` – pilchard Dec 28 '20 at 13:01
  • have I misinterpreted the standard? So the time is already compliant with the offset of the string – Bertuz Dec 28 '20 at 13:04
  • The offset at the end indicates the change that has been applied to GMT already, so your example string is equivalent to `2019-05-30T06:00:00.000Z` your best bet is probably to extract the offset from the string before changing to a date since after that the Date always accounts for local machine offset. see: [How to ISO 8601 format a Date with Timezone Offset in JavaScript?](https://stackoverflow.com/questions/17415579/how-to-iso-8601-format-a-date-with-timezone-offset-in-javascript) – pilchard Dec 28 '20 at 13:07
  • gotcha! Still, I need to show 07:00, not the local time. I'll change the question, thanks. – Bertuz Dec 28 '20 at 13:20
  • 1
    I generally like using the native Date object, but for this case [momentjs](https://momentjs.com/guides/#/parsing/) might be simplest. It allows you to keep a date in it's specified offset – from the docs: 'If your date format has a fixed timezone offset, use moment.parseZone: `moment.parseZone("2013-01-01T00:00:00-13:00");` ...results in a date with a fixed offset: "2013-01-01T00:00:00-13:00"' – pilchard Dec 28 '20 at 14:19

1 Answers1

2

Without resorting to a library the best option you have presently is:

const input = "2019-05-30T07:00:00.000+01:00";
const localTime = input.substring(11, 19); // assuming you want to truncate milliseconds
console.log(localTime);

The reason is that when parsing such as string using the Date object, the offset information is applied, but then it is discarded. In other words, all of the following are equivalent:

new Date("2019-05-30T07:00:00.000+01:00")
new Date("2019-05-30T06:00:00.000Z")
new Date(1559196000000)

The only thing actually stored within the Date object is the value 1559196000000. Thus, no amount of manipulating the Date object after creating it will be guaranteed to give you back the local hour as it was originally presented in the UTC+1 offset.

Libraries like Luxon and Moment deal with this by retaining the offset and/or original string in a separate internal field. The Date object has no such field.

In the not-too-distant future, JavaScript will be able to handle this natively using the objects and functions proposed by Temporal. For now, you can parse the string manually or use a library.

Matt Johnson-Pint
  • 230,703
  • 74
  • 448
  • 575
  • 1
    Not super fluent in that one, but looks like it can do it with something like: `new spacetime('2019-05-30T07:00:00.000+01:00').format('time-24')` or `new spacetime('2019-05-30T07:00:00.000+01:00').format('{hour-24-pad}:{minute-pad}:{second-pad}')` etc. – Matt Johnson-Pint Dec 29 '20 at 19:46