Baseweb: TimezonePicker is too opinionated about "noisy" timezones

Created on 29 Jun 2019  路  6Comments  路  Source: uber/baseweb

Current Behavior

I am situated in timezone "America/Guayaquil". After scrambling over my timezone not being default selected and reading the TimezonePicker code, it looks like it's filtering "noisy" timezones (and mine seems to be such). But that has the unwanted side effect of removing the option that could match with Intl.DateTimeFormat().resolvedOptions().timeZone; which makes it either complicated or impossible to have the current user timezone default selected in the dropdown.

Expected Behavior

Filtering should consider the current user timezone and not filter that timezone to allow a default selection. In addition, it should either be possible to disable the filtering completely with a prop to get a complete unfiltered list.

Your Environment

| Tech | Version |
| ------- | ------- |
| Base UI | v8.0.2 |
| React | 16.8.6 |
| browser | Chrome 75.x |

  • [x] I have searched the issues of this repository and believe that this is not a duplicate.
enhancement good first issue help wanted

All 6 comments

I dug into this more with the intent to attempt a fix.

I first thought that my timezone was just being filtered and I would be able to not filter it, if this is the current user timezone. So I removed the filter in timezone-picker.js to see my timezone default selected. That did not happen. It looks like my timezone America/Guayaquil is a "sub named zone" below America/Lima which gets filtered away in the timezone support package.

That means this fix seems even more complex than I first thought and while this may affect only a small percentage of users, it's a bit of a dealbreaker for me.

Would it somehow be possible to tweak the code so one can pass along the current offset when loading up the <TimezonePicker /> and then the code would match that and display the first found timezone that is with that offset? For me that could be either Lima or Panama and while neither are the exact correct in naming, at least my UI would be loading the correct timezone and the rest of my component would be able to use the timezone to show the correct date/time.

At this time it does not seem possible to pass a property to set the default selected timezone.

Hey @houmark 馃憢

I took a look into this. If you know the offset and the label you want for a specific timezone that isn't included, could you not add this via overrides of the Select? overrides allows you to hook into the timezone options and add anything you like. You could then also set a default via the Select props.

<TimezonePicker
  overrides={{
    Select: {
      component: props => (
        <Select
          {...props}
          options={[
            ...props.options,
            {
              id: 'JHEY/TIME',
              label: 'JHEY TIME!',
              offset: 100
             },
          ]}
        />
      )
    },
  }}
/>

Hey @jh3y!

Thanks for your feedback. I considered that option, but never got to try it. But if you are in fact in a time zone that's already in the list, won't I have duplicates? How can I know? I guess I can look at the list of countries before in some way.

Hey @houmark 馃憢

No problem. That's true. The TimezonePicker uses timezone-support for its list of time zones.
If you were to override the component in the Select override, you could compare the list of available timezones to the desired timezone by referencing props.options 馃憤

<TimezonePicker
  overrides={{
    Select: {
      component: props => {
        let options = [...props.options]
        if (!props.options.filter(timezone => timezone.id === 'SOME_TIMEZONE/TIME').length) {
          options = [...options, { id: 'SOME_TIMEZONE/TIME', label: 'SOME_TIMEZONE', offset: 200 }] 
        }
        return (
          <Select
            {...props}
            options={options}
        />
      )
    },
  }}
/>

Nice. This seems like a decent hack, and when used with a dynamic value, it could work nicely. I will try this out and post the final solution here in case anyone else may have interest in it.

Actually I think this should go into the core of this component to add the time zone if not found, so that it will work and correctly select any time zone, even if it's not in the default list.

Thanks again @jh3y!

Overriding in Baseweb is something I still am not too comfortable with, but it is really powerful. There really should be more examples of overrides like this in the docs site to get people started on tweaking and give inspiration to similar overrides.

Here's my final solution, which dynamically uses the current user time zone, but only if not already existing in the default ones. The added option is sorted into the existing list which makes it possible to make it appear as if it was always there.


const currentTime = new Date();
const myTimeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;
let currentTimezoneOffset = currentTime.getTimezoneOffset();

<TimezonePicker
  overrides={{
    Select: {
      component: props => {
        let options = [...props.options]
        if (!props.options.filter(timezone => timezone.id === myTimeZone).length) {
          options = [...options, {
            id: myTimeZone,
            label: myTimeZone.replace(/ /g, ' ') + ' (GMT ' + formatZonedTime({ zone: { offset: currentTimezoneOffset } }, 'Z') + ': your current time zone)',
            offset: currentTimezoneOffset
          }].sort((a, b) => b.offset - a.offset)
        }
        return (
          <Select
            {...props}
            options={options}
          />
        )
      },
    }
  }}
/>

Hope it helps someone out!

Was this page helpful?
0 / 5 - 0 ratings