libast/tm: DST offset and contemporaneous time zone fixes.#1008
Open
pghvlaans wants to merge 9 commits into
Open
libast/tm: DST offset and contemporaneous time zone fixes.#1008pghvlaans wants to merge 9 commits into
pghvlaans wants to merge 9 commits into
Conversation
Author
|
Tested on Slackware64 -current (glibc), Void (musl), FreeBSD, OpenBSD, omnios (attributes and printf only) and NetBSD. I don't currently have a macOS VM. |
Author
|
8b003db broadens the scope a bit. I can revert it and make a different PR after this one is merged if that would be more convenient. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
RE #976, 98800e9
Pre-u+m code in
tminit.csets the standard (ST) and daylight savings time (DST) offsets by checking times over the previous year of the time requested to compare DST status and offsets from UTC. If no offset change is detected, the DST offset is set equal to the ST offset.Although assigning the DST offset in this way is counter-intuitive, it does not result in incorrect times being reported so long as two implicit assumptions are met:
The first assumption fails on
muslLinux systems (which would not appear until well after the code in question was written).muslinterprets POSIX timezone specifications with a DST name but without rules as being DST year-round.tminit.ctherefore calculates both the DST and ST offsets as equal to the overall UTC offset, which is applied twice when reporting times. Becausemuslapparently disregards the topzoneinfodirectory, even common aliases such asPST8PDTreturn wildly inaccurate results (rather than the one-hour errors that/bin/datewould suggest onmuslsystems).The second assumption is broken at all times and places between a historical timezone change and a DST shift or one year later, whichever comes first. Although
Pacific/Apiabetween 2011-12-31 and 2012-04-01 yields the most striking results, there are many other examples.Fixing these problems involves relatively minor changes to
tminit.cand related tests:tminit.c, save and restore the UTC offset and DST status of the requested time; only break offset calculations for a DST shift.attributes.sh, use full POSIX timezone specifications in lieu ofEST5EDTandPST8PDT. This is necessary becausemuslapplies DST for the entire year and the time of the test is ST.printf.sh, add severalTZtests to account for different combinations of DST and ST designations across historical timezone changes. Also add anEST5EDTtest in DST.In addition, although 98800e9 introduced a fix for looking up times in zones with historical changes, it applied only to searches using seconds from the epoch. Other lookup formats still fail to change to contemporaneous zones. A convenient reproducer is:
The output should be
0and not3600.tmxdate.c, after running throughtmxdatefor the first time, compare the values ofwest,dstandisdstto ensure that a proper zone has been chosen. If the zones differ, this means that a historical change has occurred. Apply an offset and run again, repeating as necessary.printf.sh, add 'reverse' tests looking up epoch seconds by date.