Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to replace date-fns-tz #9

Open
pascuflow opened this issue Sep 22, 2024 · 8 comments
Open

How to replace date-fns-tz #9

pascuflow opened this issue Sep 22, 2024 · 8 comments

Comments

@pascuflow
Copy link

pascuflow commented Sep 22, 2024

Since date-fns 4.1.0 now includes first-class time zone support, would like to stop using date-fns-tz but having trouble getting Date from TZDate in a simple way.

For example, how would one migrate toZonedTime?

import { toZonedTime } from 'date-fns-tz'

const { isoDate, timeZone } = fetchInitialValues() // 2014-06-25T10:00:00.000Z, America/New_York

const date = toZonedTime(isoDate, timeZone) // In June 10am UTC is 6am in New York (-04:00)

renderDatePicker(date) // 2014-06-25 06:00:00 (in the system time zone)
renderTimeZoneSelect(timeZone) // America/New_York

import { TZDate } from "@date-fns/tz";

const tzDate = new TZDate(isoDate, timeZone); <----- Need a Date object here
@johnny-T
Copy link

johnny-T commented Sep 24, 2024

Hi, I am thinking about the same thing. We need something like toZonedTime from date-fns-tz, so I was trying to simulate it with TZDate. But after playing around with it, I found out some behaviours that do not seem intuitive to me when creating instances, so I wanted to share. For reference, I am working in Pacific Time zone (GMT-7) and creating dates in zone Europe/Prague (GMT+2). I am located in Prague but for testing purposes for our project, I switch to Pacific time using the Windows Date & time settings.

// this results in Sun Oct 20 2024 03:00:00 GMT+0200
new TZDate(2024, 9, 20, 3, 'Europe/Prague').toString()

// this is Sun Oct 20 2024 12:00:00 GMT+0200
new TZDate('2024-10-20 03:00:00', 'Europe/Prague').toString()

// and this is again Sun Oct 20 2024 03:00:00 GMT+0200
parse('2024-10-20 03:00:00', 'yyyy-MM-dd HH:mm:ss', TZDate.tz('Europe/Prague')).toString()

What I find mainly interesting is that the first two examples return different dates actually. The first one takes the number arguments and sets the month/day/hours in the target timezone. While the second one takes the string date and converts it from my local timezone to the target timezone, therefore adding 9 hours. The last example seems the most obvious in that the string is parsed using the reference date, which is in GMT+2.

So my question is, is this the intended behaviour? In our app, we would benefit from both approaches - converting a date to target timezone and creating a date in the target timezone. We would like to get rid of date-fns-tz, but there is no straightforward alternative in @date-fns/tz. What would be the correct approach to this? Should I perhaps create a separate issue for this?

Thanks :)

@Garfield550

This comment was marked as outdated.

@KexyBiscuit
Copy link

Hi, I am thinking about the same thing. We need something like toZonedTime from date-fns-tz, so I was trying to simulate it with TZDate. But after playing around with it, I found out some behaviours that do not seem intuitive to me when creating instances, so I wanted to share. For reference, I am working in Pacific Time zone (GMT-7) and creating dates in zone Europe/Prague (GMT+2). I am located in Prague but for testing purposes for our project, I switch to Pacific time using the Windows Date & time settings.

// this results in Sun Oct 20 2024 03:00:00 GMT+0200
new TZDate(2024, 9, 20, 3, 'Europe/Prague').toString()

// this is Sun Oct 20 2024 12:00:00 GMT+0200
new TZDate('2024-10-20 03:00:00', 'Europe/Prague').toString()

// and this is again Sun Oct 20 2024 03:00:00 GMT+0200
parse('2024-10-20 03:00:00', 'yyyy-MM-dd HH:mm:ss', TZDate.tz('Europe/Prague')).toString()

What I find mainly interesting is that the first two examples return different dates actually. The first one takes the number arguments and sets the month/day/hours in the target timezone. While the second one takes the string date and converts it from my local timezone to the target timezone, therefore adding 9 hours. The last example seems the most obvious in that the string is parsed using the reference date, which is in GMT+2.

So my question is, is this the intended behaviour? In our app, we would benefit from both approaches - converting a date to target timezone and creating a date in the target timezone. We would like to get rid of date-fns-tz, but there is no straightforward alternative in @date-fns/tz. What would be the correct approach to this? Should I perhaps create a separate issue for this?

Thanks :)

Might be related: #10

@KexyBiscuit
Copy link

Might be related: #6

@johnny-T
Copy link

johnny-T commented Sep 24, 2024

Yes, the transpose function does the job, thanks, I completely missed that. So I assume that the different behaviour for different constructors is meant to be this way? It is slightly confusing that the resulting dates have different underlying timestamp, but I guess it can be somehow justified :).

@ElectricCodeGuy
Copy link

I just searched for all import { toZonedTime } from 'date-fns-tz' in my IDE and replaced it with import { TZDate } from "@date-fns/tz";

Then i searched for "toZonedTime" and replaced it with "new TZDate"

Everything seem to work as expected

@johnny-T
Copy link

That should work in most cases perhaps, but for example we get date string from backend that is without time zone and we need to interpret it as if it was in a particular time zone, no matter where the user is located. So we actually need the underlying milliseconds to change and for that the transpose function is great.

@camsteffen
Copy link

camsteffen commented Oct 2, 2024

new TZDate('2024-10-20 03:00:00', 'Europe/Prague')

I think the underlying problem is that TZDate wants to be a thin wrapper around Date, and so that date/time string ends up getting parsed by the Date constructor, and then the resulting absolute time will be a result of the local system timezone. This is unfortunate because clearly you don't want anything to do with the local system timezone in that code.

tl;dr - use parseISO or parse

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants