date-fns-tz parse a datestamp as if it was in a specific timezone

251 Views Asked by At

I'm often in the position of wanting to extract the UTC time for a timezone-agnostic datestamp, in a particular timezone. I don't want to "convert" the stamp to the target timezone, I want the library to assume this datestamp is already in a target time zone, and give me the UTC time it would fall in.

Lets say my time zone is: Europe/Amsterdam

I want: '2023-09-26 00:00:00' in America/New_York. So I want to tell the library "This date is Midnight on 9/26/23 in America/New_York. What is the correct Unix timestamp?"

Any strategy I try ends up converting that time to a different time in the target timezone. (GMT+2 to GMT-4). Because of daylight savings time, I can't add a timezone offset to the original datestamp. The offset changes throughout the year.

Does anyone have a strategy for this?

Edit. I've come up with something, but it feels crazy. There has to be a better way?

const stamp = '2023-09-26 00:00:00';
// correct time, but wrong TZ
const wrongTz = dateFns.parse(stamp, 'yyyy-MM-dd HH:mm:ss', new Date());
// correct time, TZ, but wrong Unix timestamp
const rightTzWrongUnix = dateFnsTz.toDate(wrongTz, { timeZone, locale });
// Actual correct UTC string datestamp in our target TZ
const stampWithTz = dateFnsTz.format(rightTzWrongUnix, 'yyyy-MM-dd HH:mm:ss XX', { locale, timeZone });
// Parse the UTC stamp
const finalDate = new Date(stampWithTz)
// This is correct!
console.log(getUnixTime(finalDate))
// >> 1695700800, Tuesday, September 26, 2023 4:00:00 GMT+0

The idea is that we can get date-fns-tz to output a string stamp that formats in the correct UTC time, with the proper timezone offset with/without daylight savings. The underlying date object rightTzWrongUnix formats properly, but internally holds the wrong Unix timestamp because thats how date-fns-tz works.

We can take that generated proper UTC stamp, read it back in with new Date(), which will now hold the real Unix utc timestamp.

0

There are 0 best solutions below