-
-
Notifications
You must be signed in to change notification settings - Fork 761
feat: add experimental noonSafe prop for timezone offsets
#2879
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Signed-off-by: gpbl <[email protected]>
Signed-off-by: gpbl <[email protected]>
Signed-off-by: gpbl <[email protected]>
Signed-off-by: gpbl <[email protected]>
Signed-off-by: gpbl <[email protected]>
Signed-off-by: gpbl <[email protected]>
Signed-off-by: gpbl <[email protected]>
Signed-off-by: gpbl <[email protected]>
Signed-off-by: gpbl <[email protected]>
noonSafe prop for timezone offsets
Signed-off-by: gpbl <[email protected]>
Signed-off-by: gpbl <[email protected]>
Signed-off-by: gpbl <[email protected]>
rodgobbi
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With this approach, we are leaning more into calling TimeZone, which would worsen the performance issues we already have: #2845.
What if we try another approach to handling time zones as you suggested?
We could fix the performance issues and these historical timezone issues altogether.
I can try some new ideas later, but this issue would take time to fix.
src/noonDateLib.ts
Outdated
| import type { DateLib } from "./classes/DateLib.js"; | ||
|
|
||
| export interface CreateNoonOverridesOptions { | ||
| timeZone?: string; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can make timeZone required and skip all internal checks,
this module is dedicated to the timeZone use case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense - I've simplified a lot the utility so that we don't need the timeZone option anymore.
src/noonDateLib.ts
Outdated
| if (!timeZone || Number.isNaN(+normalizedDate)) return normalizedDate; | ||
| const tzDate = new TZDate( | ||
| normalizedDate.getFullYear(), | ||
| normalizedDate.getMonth(), | ||
| normalizedDate.getDate(), | ||
| 12, | ||
| 0, | ||
| 0, | ||
| timeZone, | ||
| ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I first thought the approach would be to shift + 12 hours the processed date.
This approach hard sets the time to 12:00 the same day.
From the top of my head the issues this approach could have:
01:00 + 1 UTC is a different calendar day from 23:00 - 1 UTC, but are the same time 00:00 UTC.
Imagine the machine timezone is 01:00 + 1 UTC, and the timezone prop is -1 UTC.
This logic would normalize the date to 12:00 +1 UTC, which is 10:00 -1 UTC.
I feel this can cause issues, but it needs to be tested and validated.
If this is handled, lemme know how so we can validate.
The Jest runner timezone is now UTC, and the test cases in this PR are all + UTC timezone, causing the all the calculations and rendering of the calendar to be in the same day.
Could we have more test cases that cross days between the system timezone and the prop timezone?
At least one to cover both ways:
- one case where system is + UTC and timezone is - UTC, setting the system time to cause the calendar to be one day before in the calendar
- and vice versa for system in - UTC and timezone in + UTC
Signed-off-by: gpbl <[email protected]>
Signed-off-by: gpbl <[email protected]>
Adds an experimental
noonSafeprop to work around historical second-level timezone offset issues that cause calendar rendering glitches.Root Cause
When using the
timeZoneprop with historical timezones (e.g.,Asia/Dubaiin 1900 has offset+03:41:12, orAsia/Tehranfor old Persian years), JavaScript'sDateanddate-fnsround offsets to minutes. This rounding can push midnight calculations into the previous day, causing:timeZoneprop breaks Persian calendar rendering for old years (e.g. 1313) inAsia/Tehran#2842 where day 1 is repeated during DST transitions)This affects both Gregorian and Jalali calendars (Persian calendar in #2842 with
Asia/Tehranand old years like 1313).Solution
The
noonSafeprop creates date library overrides that keep all calendar math at 12:00 noon in the target timezone. By performing calculations at noon instead of midnight, we avoid the second-level offset rounding issues that occur across midnight boundaries. This ensures:Implementation
createNoonOverrides()function innoonDateLib.tsthat provides timezone-aware date utilities operating at nooncreateJalaliNoonOverrides()innoonJalaliDateLib.tsfor Jalali calendar supportDayPickercomponent: whennoonSafe={true}andtimeZoneis set, the noon overrides are merged with the dateLibdateLibprops take precedence overnoonSafeoverrides if both are providednoonSafeCloses
Fixes #2842
Notes
@experimentaland requires explicit opt-in vianoonSafepropScreen.Recording.2025-12-12.at.14.28.50.mov
Screen.Recording.2025-12-12.at.14.22.38.mov