-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
Add more support for Julian time zones POSIX rules #50131
Conversation
I couldn't figure out the best area label to add to this PR. If you have write-permissions please help me learn by adding exactly one area label. |
src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.cs
Outdated
Show resolved
Hide resolved
(nit) can you update this comment while you are in here? This only supports Refers to: src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.cs:1363 in 0c7707a. [](commit_id = 0c7707a, deletion_comment = False) |
Yes, I did it. Thanks for catching that. @stephentoub @eerhardt please let me know if you have any more comments or we good to go. Thanks. |
src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.cs
Outdated
Show resolved
Hide resolved
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.
Thanks @tarekgh. The code changes look good to me.
Thanks for your review and feedback. it was helpful. I'll not merge this before try adding some test per your suggestion. |
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.
Looks great. Thanks for adding the tests.
@@ -1296,8 +1296,7 @@ private static DateTime ParseTimeOfDay(ReadOnlySpan<char> time) | |||
{ | |||
if (date[0] != 'J') | |||
{ | |||
// should be n Julian day format which we don't support. | |||
// | |||
// should be n Julian day format. |
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.
The comment below says "February 29 is counted in leap years". but the man page for tzset says:
Jn This specifies the Julian day with n between 1 and 365.
Leap days are not counted. In this format, February 29
can't be represented; February 28 is day 59, and March 1
is always day 60.
Am I looking at the wrong thing?
If leap years can't be counted, that would explain why it's not very useful past Feb 28...
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 think you got confused, this is handling the n
format not the Jn
. The n
format goes from 0-365 and counts leap years.
See my comment below, but the Jn format is handled after this if.
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.
Oh..nuts
// numbers less than 59 (up to Feb 28). Otherwise we'll skip this POSIX rule. | ||
// We've never encountered any time zone file using this format for days beyond Feb 28. | ||
|
||
if (int.TryParse(date, out int julianDay) && julianDay < 59) |
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.
Per the tzset man page pasted above, the value seems to start at 1, not 0..?
I may just be confused though, as I don't think I understand why the J format exists, unless it's a way to express a day that ignores a leap day (which is the way I read the man page). Eg., your example Africa\Casablanca: <+00>0<+01>,0/0,J365/25
means from the first day of the year to the last day of the year, whether it's a leap year or not. Also, this example would not be handled by this code as 365 is larger than 58 anyway?
cc @tarekgh
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 believe the Jn format was already supported, this section is adding the n
format. Which based on the man page is:
n This specifies the zero-based Julian day with n between 0 and 365. February 29 is counted in leap years.
Which is a regular int number. The Jn format which you are referring to is handled after this if:
// Julian day |
Which is when date[0] == 'J'
.
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.
What about the question about only supporting up to Feb 28, when the example given is 365 ? I may well be still confused haha
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.
In this bizarre counting system, Feb 29 doesn't exist. Dec 31st is always day 365, even in a leap year.
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.
@danmoseley we are fully support Jn rule and partially support n rule. Jn rule is not differentiating between leap year and non-leap years. So, Feb 29th cannot be expressed with the Jn rule. i.e. if using J60 it is always March 1st and never be Feb 29th.
In the other hand, n rule account for leap years. note as mentioned before this rule is zero based rule. if specify 59
it means March 1st when the year is not leap year and will mean Feb 29th in the leap years. anyway, I never encountered any time zone file use this rule to specify a day after Feb 28th.
Let me know if there is anything unclear here.
[InlineData("<+00>0<+01>,A/0,J365/25", 0, 0, false)] | ||
public static void NJulianRuleTest(string posixRule, int dayNumber, int monthNumber, bool shouldSucceed) | ||
{ | ||
string zoneFilePath = Path.GetTempPath() + "dotnet_tz"; |
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.
Tiny nit, using Path.GetRandomFileName()
or some other source of randomness (as FileCleanupTestBase.GenerateTestFileName(..) does for example) would allow this test to be run concurrently with itself, eg., if someone runs debug and release tests together.
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.
that is a good idea.
On Linux the time zone files can include the rules posix format https://man7.org/linux/man-pages/man3/tzset.3.html. We already parse such format successfully except the Julian n day format. After investigating different Linux distro zone files for all zones, I found only
rhel
based distros (e.g.RHEL
,Centos
, andAmazon Linux
) are using this Julian n rules for the following zones:Also, it is used only for convenience to specify January 1st date. From the experience with the time zone, I cannot think in any case that need to use this rule to specify dates after February 28. Considering that, we can handle this rule if the specified date in the rule would be from Jan 1 to Feb 28.
So, this change is to allow parsing this rule and we'll only fail in case if getting dates past Feb 28 which is very uncommon and very unlikely be used in the future.
#25933