javascriptdatetimedate-fnsdate-fns-tz

How do I show a UTC time in local time using date-fns?


I know this has been asked before, but I have some kind of inability to process time zones and just can't get my head around it.

My React app is currently rendering a calendar, and I'm having difficulty with time zones. The dates of events are stored in UTC, and I retrieve a list of events and render them. I want to show the start time of each event in the user's local time, but I can't get it to work. I've also installed date-fns-tz, but it doesn't seem to be doing anything different.

Currently for each event I have a startDate in UTC, which looks like this: 2024-08-27T08:30:00.0000000.

If I display it using format(startDate, "HH:mm") I get: 08:30 (as expected).

However, in my time zone ("Europe/London") this event will actually start at 9.30 (my time), and that's what I want to display.

I can get the time zone from the browser using const tz = Intl.DateTimeFormat().resolvedOptions().timeZone;, but I'm not sure how to use that to convert and show the time.

I've tried using date-fns-tz's version of format: format(startDate, "HH:mm", { timeZone: "Europe/London" }) but still get 8:30.

I've also tried toZonedTime: toZonedTime(startDate, "Europe/London") which converts the startDate to Tue Aug 27 2024 08:30:00 GMT+0100 (British Summer Time) - I'm not sure if that's the correct time (British Summer Time is 1 hour ahead of UTC, so UTC+1). In any case, when I print it out, it still shows as 8:30.

Essentially, I have a startDate in UTC which is 8:30; however, when the event starts my watch will show 9:30, so 9:30 is what I want to display.


Solution

  • My trick is shift the Date object forward or backward in time to whichever time zone you need, which is equivalent to changing time zones.

    You can shift a Date object into the browser's time zone using the following:

    const convertToBrowserTimeZone = (utcDate) => {
        const browserTimeZoneOffsetMs = -60000 * (new Date()).getTimezoneOffset();
        return new Date(utcDate.getTime() + browserTimeZoneOffsetMs);
    }
    

    Then to format a UTC time in the browser's time zone:

    format(convertToBrowserTimeZone(startDate), "HH:mm")