Feature request: Automatically detect user timeZone based on GMT offset
emrysal opened this issue ยท 16 comments
We've got a usecase where we want the use the dayjs.tz.guess() function, which for Italy for example may return Europe/Rome. This wouldn't resolve to anything in this case.
Perhaps it is an idea to do some kind of map of GMT offset to timeZone?
Hey thanks for bringing this up!
So if I understand you correctly, you want to be able to pass in a GMT offset (i.e. GMT+2:00
) and get back the full timezone object? spacetime
supports something similar, does that fulfill your usecase? If not, maybe moment-timezone
does?
So the usecase is that we want to default select option to the applicable timeZone according to the user browser settings; this would work if the timeZone selection included all the timeZones that exist, but that list is very user unfriendly ux wise (hense we use this select). But we'd still like to be able to default the applicable select option based on user browser configuration.
So like: Europe/Rome
=> Europe/Brussels
(or whichever timezone Rome actually is in)
Ah okay, so we can probably relatively easily select the default timezone via the users browser language / country headers or something like that.
Would that fulfill your use case?
How's this?
const [timezone, setTimezone] = useState<ITimezone>(Intl.DateTimeFormat().resolvedOptions().timeZone);
return <TimezoneSelect value={timezone} onChange={setTimezone}/>
I don't think this works in IE11 though.
https://caniuse.com/?search=DateTimeFormat
Yeah just putting it as the default value in the useState call is what I would have done too. I didn't know the new Intl
object had this though, thats awesome!
Regarding IE11, thats okay I dont plan on going out of my way to support that anyway..
Hey so I've released a new version last night with a bunch of clean up.
Wasn't sure whether to put this into a prop the user could enable (i.e. showUserTimezoneByDefault
) or something like that.
But just decided to throw it in the readme for now since it makes more sense for the user to use your little Intl
snippet in "userland" when they're initialising the state.
Thanks again for the tip!
@ndom91 You are very welcome. Thanks for making a wonderful open source component ๐
Going to close this for now, if anyone comes across this looking for similar behavior - checkout @ndrwksr 's workaround in the comment above (#25 (comment)), or in the README.
@ndom91 What I meant was what happens in the case the timezone is missing from the select. Attached a screenshot of what happens when the timeZone detected is Europe/Rome.
Added after initial comment: So Intl.DateTimeFormat().resolvedOptions().timeZone is a good way to do it, but then the missing piece of the puzzle is somehow - and I'm not quite sure what the appropriate solution is here - map back to one of the options within react-timezone-select.
Ah gotcha.
Yeah so there's two ways to deal with this.
Either I expand the interior map to include every timezone in that "Europe/Rome" format.
Or I make this "setUserTimezoneByDefault" thing an internal prop, and then I can match user timezones that don't exist (like Europe/Rome) by offset to the matching existing choice (Europe/Berlin or Europe/Amsterdam I think it'd be).
What do you think?
I'm up for doing the second variant, that shouldn't be too hard. And doesn't change the user facing api other than adding a new boolean prop.
The Dumb approach I came up with is to indeed get a list together of all timezones in existance, and map them to the relevant "Short list". I think it is desireable from this component POV to deal with valid timezones that are not part of the component display (in case people want to do this). I was wondering if there were smarter ways like detecting an entered timezone GMT offset, and then find the item in the list with the same GMT offset rules.
By logic, I think this belongs within the parseTimezone
function (sidenote, this is typehinted ITimeZone but I think it's mixed at that point, either ITimezone or string, but alas). The way it can be handled is that when you pass "Europe/Rome" it returns an ITimeZone interface with Europe/Amsterdam, as that is the relevant match.
@emrysal I believe this would be helpful:
https://github.com/spencermountain/timezone-soft/
Btw @emrysal - regarding the union type ITimezone
, this was done this way to support allowing people to just pass in "Europe/Amsterdam", for example, instead of the whole object. Mostly for backwards compatibility reasons. Maybe we should do a major version bump and just remove that..
Hey everyone, @emrysal's PR to match any possible timezone to one in our list, has been merged! ๐
This means you can safely use the Intl.DateTimeFormat().resolvedOptions().timeZone
trick during state initialisation, and get a valid timezone selection out of this component ๐
There is a problem with using Intl.DateTimeFormat().resolvedOptions().timeZone
as a way to set the user timezone. say for example your timezone is Paris, Intl sets it as Europe/Paris
and NOT Europe/Brussels
which your library supports. now the selection works as you mentiend. Here is the Problem: I use your import {allTimezones} from "react-timezone-select";
to display the timezone label allTimezones[props.timeZone]
this evaluates to undefined
. because you don't support all timezone so Europe/Paris
is undefined
. I'm considering using GMT as default Selection and always forcing the user to select the timezone himself, because I really like your allTimezones
object.
There is a problem with using
Intl.DateTimeFormat().resolvedOptions().timeZone
as a way to set the user timezone. say for example your timezone is Paris, Intl sets it asEurope/Paris
and NOTEurope/Brussels
which your library supports. now the selection works as you mentiend. Here is the Problem: I use yourimport {allTimezones} from "react-timezone-select";
to display the timezone labelallTimezones[props.timeZone]
this evaluates toundefined
. because you don't support all timezone soEurope/Paris
isundefined
. I'm considering using GMT as default Selection and always forcing the user to select the timezone himself, because I really like yourallTimezones
object.
Yeah this is a known issue, someone has suggested auto detecting the city and generating the timezones dynamically in this issue, but no movement yet.