与 AdjustmentRule 相比,.NET TimeZoneInfo 中的意外 DST 偏移

Unexpected DST offset in .NET TimeZoneInfo compared to the AdjustmentRule

我正在尝试为英国切换到 BST 的时间点计算正确的 DST 偏移量,该时间点应该是 2021 年 3 月 28 日凌晨 1 点。

我这里有一个fiddle:https://dotnetfiddle.net/8gdVIG

为了完整起见,这是我的代码 运行:

var timeZoneInfo = TimeZoneInfo.GetSystemTimeZones().FirstOrDefault(tzi => tzi.Id.Equals("Europe/London", StringComparison.InvariantCultureIgnoreCase));

Console.WriteLine($"No. of adjustment rules: {timeZoneInfo.GetAdjustmentRules().Count()}");
var firstRule = timeZoneInfo.GetAdjustmentRules().FirstOrDefault(r => new DateTime(2021,03,28,1,59,0) >= r.DateStart && new DateTime(2021,03,28,1,59,0) <= r.DateEnd);
Console.WriteLine($"            Day: {firstRule.DaylightTransitionStart.Day}");
Console.WriteLine($"      DayOfWeek: {firstRule.DaylightTransitionStart.DayOfWeek}");
Console.WriteLine($"IsFixedDateRule: {firstRule.DaylightTransitionStart.IsFixedDateRule}");
Console.WriteLine($"          Month: {firstRule.DaylightTransitionStart.Month}");
Console.WriteLine($"      TimeOfDay: {firstRule.DaylightTransitionStart.TimeOfDay}");
Console.WriteLine($"           Week: {firstRule.DaylightTransitionStart.Week}");
Console.WriteLine($"Offset at 01:59 on 2021-03-28: {timeZoneInfo.GetUtcOffset(new DateTime(2021,03,28,1,59,0)).Hours}");

结果为:

No. of adjustment rules: 244
            Day: 28
      DayOfWeek: Sunday
IsFixedDateRule: True
          Month: 3
      TimeOfDay: 01/01/0001 01:00:00
           Week: 1
Offset at 01:59 on 2021-03-28: 0

然而凌晨 2 点的偏移量是我预计凌晨 1 点的 1 小时。

Console.WriteLine($"Offset at 02:00 on 2021-03-28: {timeZoneInfo.GetUtcOffset(new DateTime(2021,03,28,2,0,0)).Hours}");

输出:

Offset at 02:00 on 2021-03-28: 1

为什么凌晨 1 点的 UTC 偏差不是 1 小时?我真的需要 Noda Time 才能获得正确的本地 DST 偏移量吗?

2021-03-28T01:00:00 在英国时区不存在 - 01:59:00 也不存在。我们跳过 at 凌晨 1 点直接到凌晨 2 点。因此,您的代码中打印的第一个值是无效的 date/time 值。

documentation(令人惊讶地)清楚这一点:

If dateTime is invalid, this method returns a TimeSpan object that reflects the difference between UTC and the time zone's standard time.

并且由于英国的标准时间与UTC相同,打印0是正确的。