ndom91/react-timezone-select

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.

image

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.

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 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.

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.