Search code examples
javascriptdatedatetimedate-fns

How to convert JS Date from UTC 'Z' to timezoned date


Hey I am receiving dates from a database which saves these dates as UTC. When I print one of the dates with console.log it looks like this 2021-04-07T07:00:00.000Z.

Now I want to convert it into Europe/Berlin time. But not as a String, I want it as Javascript Date.

What i tried to do

I installed date-fns and date-fns-tz and I tried to use multiple functions from these packages but nothing seems to work properly or returns the correct date but again as with 'Z' suffix.

Example where testDate is the Date mentioned before

// using utcToZonedTime from date-fns-tz
console.log(utcToZonedTime(testDate, 'Europe/Berlin'));
// output: 2021-04-07T07:00:00.000Z

// using getTimezoneOffset from date-fns-tz
console.log(getTimezoneOffset('Europe/Berlin', testDate) / 1000 / 60)
// output: 120

// using addMinutes from date-fns to add the Offset manually
  console.log(
        addMinutes(
          testDate,
          getTimezoneOffset('Europe/Berlin', testDate) / 1000 / 60,
        ),
      );
// output: 2021-04-07T09:00:00.000Z

Only the last case output the correct Date but still in wrong format. How can I get a normal date in my time zone.


Solution

  • Now I want to convert it into Europe/Berlin time. But not as a String, I want it as Javascript Date.

    That is not possible. The JavaScript Date object does not contain any time zone information whatsoever. The only thing it contains is a Unix timestamp with milliseconds precision. In other words, the Date object encapsulates the number of milliseconds since 1970-01-01 00:00:00.000 UTC (not counting leap seconds). You can see this value directly with .getTime(), .valueOf(), or by any mechanism that converts the Date object to a Number.

    When one observes a Date object and sees a time zone or a value in a particular time zone, that behavior is occurring at runtime in the function itself. For example, the toString function of the Date object uses the local time zone of the computer when it converts the internal UTC-based timestamp to the computer's local time before returning a string that has formatted that result.

    Most functions on the Date object work in either UTC or in the computer's local time zone (as described). The only ones that work with other time zones are the toLocaleString, toLocaleDateString, and toLocaleTimeString functions, which will accept an IANA time zone identifier in the timeZone option. Like the toString function, they only use this time zone when generating a string. They do not retain it.

    In short, the Date object does not contain a time zone, so what you ask for is not possible.

    A couple of other things:

    • Don't call console.log directly on a Date object. That behavior is undefined. Some implementations return the value of toString while others return the value of toISOString.

    • Don't ever try to add/subtract an offset on a date/time unless you really know what you are doing. In most cases, you aren't adjusting for time zone but are actually choosing a different point in time.

    • Yes, Z at the end of an ISO 8601 timestamp means that the date and time presented are in terms of UTC.