'How to set up only time in date-fns and still keep the timezone in javascript
I currently have the following use case:
- User receives a date in UTC from the backend
- This date is transformed into local time for displaying purposes
- The date is displayed in different inputs. One input for
date
and other fortime
- User can select
time
independently - The date should be sent back to the backend in UTC format as well
I'm not very experienced with time zones and I'm getting beaten by trying to allow the user to set up only the time
(or date
) in a datetime field.
My pseudo code is the following:
- When receiving the from backend simply convert the date to show it to the user, making the orignal date stay in UTC
- When the user picks the
hour
andminute
(all in one action) usesetHours
andsetMinutes
fromdate-fns
library - Use native
toISOString()
to set in models
Code so far [playground]:
import { utcToZonedTime, format } from "date-fns-tz";
import { setHours, setMinutes } from "date-fns";
const UTCStringdate = "2022-04-06T10:00:00.000000Z";
const userTimezone = "Asia/Bangkok";
const localizedTime = utcToZonedTime(UTCStringdate, userTimezone);
// Prints the correct information
// 10:00 in UTC is equal to 17:00 in Bangkok
console.log(format(localizedTime, "HH:mm"));
// Now I expext to set only the `minutes` and `hours`
// to this `localizedTime` so that I can update the backend
const [hours, minutes] = "10:30".split(":");
// Somewhere over here the `setHours` and `setMinutes`
// is turning the Date object into my own timezone
// and not using `Asia/Bangkok` timezone anymore
let newTime = setHours(localizedTime, hours);
newTime = setMinutes(newTime, minutes);
// Now I expect to print 17:30 since we only
// set up 30 minutes forward than the original one
// but it ends up printing 10:30
console.log(format(newTime, 'HH:mm'));
I understand that somewhere along the way (most likely in setHours
and setMinutes
) the date-fns
library turns back the localizedTime
back into my own timezone, completely ruining the idea of turning the Asia/Bangkok
time into UTC
.
Questions
First, is this the best approach to manipulate only the time
part of a date when considering timezones? If not, anyone can point me to articles? I wasn't able to find anything on the topic
Second, how can I use setHours
and setMinutes
and still maintain the timezone
?
Solution 1:[1]
There are no multiple time zones in JavaScript. There is UTC and there is your local one. What date-fns-tz does, is adjusting the time to the chosen user time zone. In your example, you can see this when printing both the original and the localized time
const utcTime = new Date(UTCStringdate);
console.log(utcTime.toISOString()); // -> 2022-04-06T10:00:00.000Z
console.log(localizedTime.toISOString()); // -> 2022-04-06T14:00:00.000Z
To solve your issue, convert UTC time to users time and let the user to adjust hours and minutes in his local time zone. After that, convert the time object back to UTC using zonedTimeToUtc
newTime = zonedTimeToUtc(newTime, userTimezone);
and then use newTime.toISOString() to send it back to the server.
console.log(newTime.toISOString());
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | ochakov |