[WIP] Add timezone selector to DateTimeWidget for event start and end#8304
[WIP] Add timezone selector to DateTimeWidget for event start and end#8304davisagli wants to merge 2 commits into
Conversation
|
@stevepiercy Any feedback before I spend more time on this? |
Thanks for picking this up. This is hella tricky to implement, especially during those periods when one timezone has DST in effect and the other doesn't. I'd avoid automatic adjustment, keeping it consistent for the user. My concern is that moment.js will still screw up the displayed datetime. The most common use case is for Plone Conference, where it shows the converted local time of an event to the page visitor, like 1:30 AM for the keynote, which is just wrong. https://2025.ploneconf.org/schedule/keynotes And I'm not able to download an .ics file that has the correct timezone. But now I'm feature creeping out of scope... |
So in this scenario:
I don't have a strong opinion on this one myself, but I thought the second option is less surprising (and it's what google calendar does).
We have to be explicit about what timezone to use now that we have that information available, whether we do that using momentjs or not. For display use cases like the conference schedule, it's easy to switch to formatting the time using Intl.DateTimeFormat, which provides easier control over the timezone. I'm just keeping momentjs for the input widget, because it currently uses react-dates which depends on momentjs. And I think I've figured out a way to set the offset on the momentjs object so that it appears in the correct timezone in the widget.
That one is definitely a separate issue. The ICS download is implemented as a browser view in plone.app.event so isn't even in the same packages I've been touching. The changes in plone.restapi should make sure that the datetime value is stored with the correct timezone on the backend, so then it should be pretty straightforward to make the ics export use that information. |
If the user changes the timezone, then they should manually change the time and possibly the date. Automatic adjustment should be avoided. Otherwise, the sooner we kick moment.js to the curb, the better. I understand that it's not altogether possible yet. |
So just to be clear, you would expect the time to show as 3am after the user changes the timezone in the scenario I gave? (We're either adjusting the display or adjusting the value, so I'm not certain which one you mean by no automatic adjustment.) |
Now I'm not sure. I thought that the user was creating or editing an event. Whatever the user inputs is what the user should get, and there should be no "helpful" automatic adjustment to the values that the user enters. For example:
I hope that clarifies the complete scope of the matter. If this PR resolves only parts of it, then please clarify. Thank you! |
|
@davisagli @stevepiercy I agree with that scenario just outlined by steve above. The user enters the date and time and changing the timezone would not change the values entered in the date and time widget. In the z3c.form datetime widget data converter we're first creating a native datetime value and then pop the timezone information onto it, which is consistent to the outlined scenario: https://github.com/plone/plone.app.z3cform/blob/2d9cfdfc8ab3544aa7135b89210a100e7ed2436e/src/plone/app/z3cform/converters.py#L125 |
|
@stevepiercy Yep, that's what I'm aiming for. (Sorry if I made it confusing earlier. We have to update the internal value so that the value shown to the user is the same once the new timezone offset is applied.) Items 1-6 in your example are already implemented with the combination of this PR and the plone.restapi PR that it depends on. Item 7 is not implemented yet, but that's what I plan to do. |
|
@thet and @davisagli I just want to say thank you for verifying, and for your efforts on this much needed improvement. |
| onBlur={() => setOpen(false)} | ||
| options={Intl.supportedValuesOf('timeZone').map((tz) => ({ | ||
| value: tz, | ||
| label: tz, |
There was a problem hiding this comment.
For the future: we should translate this - TIL from Gemini - using CLDR: https://en.wikipedia.org/wiki/Common_Locale_Data_Repository
For example "Europe/Vienna" -> "Mitteleuropäische Zeit - Wien (GMT+2)".
An example Python Code:
from babel.dates import get_timezone_name
from zoneinfo import ZoneInfo
tz = ZoneInfo("Europe/Vienna")
# Liefert "Mitteleuropäische Sommerzeit" für das aktuelle Datum
print(get_timezone_name(tz, locale="de_AT", width="long"))However, I'd still like to find timezones by it's English identifier, as I'm used to do so.
But this is definitely for a future improvement. I'm just mentioning this here.
|
|
||
| const renderWidget = !(id === 'end' && formData?.open_end); | ||
|
|
||
| const localTimezone = Intl.DateTimeFormat().resolvedOptions().timeZone; |
There was a problem hiding this comment.
I was chewing on the Intl timezone, because we have a portal timezone and potentially a timezone set by the user in the @@personal-preferences.
But using Intl here makes a lot of sense!
I think the timezone setting in the @@personal-preferences is obsolete and should be removed.
I have created a draft PLIP here: plone/Products.CMFPlone#4337

Refs plone/Products.CMFPlone#4115
This updates the existing DateTimeWidget to display the selected timezone for event start and end dates, and provide a selector for changing it.
Depends on the REST API support in plone/plone.restapi#2018
Notes:
To do:
Intentionally out of scope for this PR:
@plone/componentsin the long term (for better a11y and avoiding momentjs), but that was a bigger project than I could tackle today, and I wanted to implement this in a way that can potentially be merged for Volto 19 without breaking changes.