Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit 2d996fc

Browse files
eerhardtAnipik
authored andcommitted
Stop throwing exception in TimeZoneInfo POSIX parsing (#27969)
IsDaylightSavingTime_CasablancaMultiYearDaylightSavings fails on rhel.8 When parsing the tzdata POSIX string that contains an 'n' Julian date, we are currently throwing an exception, and then falling back to a TimeZoneInfo without DST enabled. However, this is a mistake because there are other DST transitions that were read from the tzdata file that are valid and usable. We shouldn't be throwing that information away. So instead, we now skip the POSIX string if we detect an unsupported 'n' Julian date, and just use the last transition as the AdjustmentRule for all the DateTimes in the future. This way we can still make DST determinations correctly for some DateTimes. Fix https://github.com/dotnet/corefx/issues/42192
1 parent 5936083 commit 2d996fc

File tree

2 files changed

+26
-33
lines changed

2 files changed

+26
-33
lines changed

src/System.Private.CoreLib/Resources/Strings.resx

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2704,9 +2704,6 @@
27042704
<data name="InvalidTimeZone_InvalidJulianDay" xml:space="preserve">
27052705
<value>Invalid Julian day in POSIX strings.</value>
27062706
</data>
2707-
<data name="InvalidTimeZone_NJulianDayNotSupported" xml:space="preserve">
2708-
<value>Julian n day in POSIX strings is not supported.</value>
2709-
</data>
27102707
<data name="InvalidTimeZone_NoTTInfoStructures" xml:space="preserve">
27112708
<value>There are no ttinfo structures in the tzfile. At least one ttinfo structure is required in order to construct a TimeZoneInfo object.</value>
27122709
</data>

src/System.Private.CoreLib/shared/System/TimeZoneInfo.Unix.cs

Lines changed: 26 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -985,21 +985,11 @@ private static void TZif_GenerateAdjustmentRule(ref int index, TimeSpan timeZone
985985
// NOTE: index == dts.Length
986986
DateTime startTransitionDate = dts[index - 1];
987987

988-
if (!string.IsNullOrEmpty(futureTransitionsPosixFormat))
989-
{
990-
AdjustmentRule? r = TZif_CreateAdjustmentRuleForPosixFormat(futureTransitionsPosixFormat, startTransitionDate, timeZoneBaseUtcOffset);
991-
992-
if (r != null)
993-
{
994-
if (!IsValidAdjustmentRuleOffest(timeZoneBaseUtcOffset, r))
995-
{
996-
NormalizeAdjustmentRuleOffset(timeZoneBaseUtcOffset, ref r);
997-
}
988+
AdjustmentRule? r = !string.IsNullOrEmpty(futureTransitionsPosixFormat) ?
989+
TZif_CreateAdjustmentRuleForPosixFormat(futureTransitionsPosixFormat, startTransitionDate, timeZoneBaseUtcOffset) :
990+
null;
998991

999-
rulesList.Add(r);
1000-
}
1001-
}
1002-
else
992+
if (r == null)
1003993
{
1004994
// just use the last transition as the rule which will be used until the end of time
1005995

@@ -1008,22 +998,22 @@ private static void TZif_GenerateAdjustmentRule(ref int index, TimeSpan timeZone
1008998
TimeSpan daylightDelta = transitionType.IsDst ? transitionOffset : TimeSpan.Zero;
1009999
TimeSpan baseUtcDelta = transitionType.IsDst ? TimeSpan.Zero : transitionOffset;
10101000

1011-
AdjustmentRule r = AdjustmentRule.CreateAdjustmentRule(
1001+
r = AdjustmentRule.CreateAdjustmentRule(
10121002
startTransitionDate,
10131003
DateTime.MaxValue,
10141004
daylightDelta,
1015-
default(TransitionTime),
1016-
default(TransitionTime),
1005+
default,
1006+
default,
10171007
baseUtcDelta,
10181008
noDaylightTransitions: true);
1009+
}
10191010

1020-
if (!IsValidAdjustmentRuleOffest(timeZoneBaseUtcOffset, r))
1021-
{
1022-
NormalizeAdjustmentRuleOffset(timeZoneBaseUtcOffset, ref r);
1023-
}
1024-
1025-
rulesList.Add(r);
1011+
if (!IsValidAdjustmentRuleOffest(timeZoneBaseUtcOffset, r))
1012+
{
1013+
NormalizeAdjustmentRuleOffset(timeZoneBaseUtcOffset, ref r);
10261014
}
1015+
1016+
rulesList.Add(r);
10271017
}
10281018

10291019
index++;
@@ -1115,15 +1105,20 @@ private static TZifType TZif_GetEarlyDateTransitionType(TZifType[] transitionTyp
11151105
daylightSavingsTimeSpan = TZif_CalculateTransitionOffsetFromBase(daylightSavingsTimeSpan, baseOffset);
11161106
}
11171107

1118-
TransitionTime dstStart = TZif_CreateTransitionTimeFromPosixRule(start, startTime);
1119-
TransitionTime dstEnd = TZif_CreateTransitionTimeFromPosixRule(end, endTime);
1108+
TransitionTime? dstStart = TZif_CreateTransitionTimeFromPosixRule(start, startTime);
1109+
TransitionTime? dstEnd = TZif_CreateTransitionTimeFromPosixRule(end, endTime);
1110+
1111+
if (dstStart == null || dstEnd == null)
1112+
{
1113+
return null;
1114+
}
11201115

11211116
return AdjustmentRule.CreateAdjustmentRule(
11221117
startTransitionDate,
11231118
DateTime.MaxValue,
11241119
daylightSavingsTimeSpan,
1125-
dstStart,
1126-
dstEnd,
1120+
dstStart.GetValueOrDefault(),
1121+
dstEnd.GetValueOrDefault(),
11271122
baseOffset,
11281123
noDaylightTransitions: false);
11291124
}
@@ -1214,11 +1209,11 @@ private static DateTime ParseTimeOfDay(ReadOnlySpan<char> time)
12141209
return timeOfDay;
12151210
}
12161211

1217-
private static TransitionTime TZif_CreateTransitionTimeFromPosixRule(ReadOnlySpan<char> date, ReadOnlySpan<char> time)
1212+
private static TransitionTime? TZif_CreateTransitionTimeFromPosixRule(ReadOnlySpan<char> date, ReadOnlySpan<char> time)
12181213
{
12191214
if (date.IsEmpty)
12201215
{
1221-
return default(TransitionTime);
1216+
return null;
12221217
}
12231218

12241219
if (date[0] == 'M')
@@ -1264,7 +1259,8 @@ private static TransitionTime TZif_CreateTransitionTimeFromPosixRule(ReadOnlySpa
12641259
//
12651260
// If we need to support n format, we'll have to have a floating adjustment rule support this case.
12661261

1267-
throw new InvalidTimeZoneException(SR.InvalidTimeZone_NJulianDayNotSupported);
1262+
// Since we can't support this rule, return null to indicate to skip the POSIX rule.
1263+
return null;
12681264
}
12691265

12701266
// Julian day

0 commit comments

Comments
 (0)