由System.DateTimeOffset实例报告的1883年11月19日之前的UTC偏移量令人惊讶

时间:2018-08-22 17:10:26

标签: datetime .net-core timezone utc datetimeoffset

注意:为了方便起见,使用PowerShell来演示行为,但是问题是关于System.DateTimeOffset .NET类型的行为。

注意:正如Matt Johnson所指出的,所讨论的行为仅在类似 Unix的平台 (macOS,Linux,使用.NET Core)上发生。

表面上,当System.DateTimeOffset转换本地日期时,对于1883年11月19日之前的日期,产生的时区偏移量(与UTC的偏移量)不同

考虑以下PowerShell命令:

([datetime] '1883-11-18'), ([datetime] '1883-11-19') |
  ForEach-Object { ([datetimeoffset] $_).Offset.ToString() }

Eastern Time Zone中调用时,会产生:

-04:57:00
-05:00:00

(DST(夏令时)直到1918年才发挥作用。)

我怀疑这与以下内容有关,摘录from Wikipedia,并强调:

  

[...]使美国铁路公司达成了一项协议,导致在1883年11月18日中午在全国范围内引入了标准铁路时间。 / p>

  • 任何人都可以确认并提供更多信息吗?

  • 为什么偏移偏移了3分钟?

Searching for 1883 in the entire .NET documentation仅产生以下内容,passing reference

  

[...] 1883年至1917年的美国东部标准时区,在美国实行夏令时之前

1 个答案:

答案 0 :(得分:3)

在类似Unix的平台(Linux,OSX等)上运行时,操作系统中的时区数据源自IANA time zone database。此数据集中的早期日期通过其本地平均时间(LMT)进行参考,该时间是根据参考城市的纬度和经度计算得出的。在这种情况下,以America/New_York表示的美国东部时间具有与您报告的发现相符的LMT条目。

来自tzdb

# Zone  NAME              GMTOFF    RULES  FORMAT  [UNTIL]
Zone    America/New_York  -4:56:02  -      LMT     1883 Nov 18 12:03:58
                          -5:00     US     E%sT    1920
                          -5:00     NYC    E%sT    1942
                          -5:00     US     E%sT    1946
                          -5:00     NYC    E%sT    1967
                          -5:00     US     E%sT

请注意,由于DateTimeOffset支持的偏移量精度,偏移量中的秒数在导入时会被截断。

您可以在tz数据库的the theory file中了解有关LMT的更多信息(以及更多信息)。

在Windows上,您不会看到此行为,因为Windows没有早于2006-2007过渡的Eastern Standard Time时区的时区数据。因此早于1987年的日期可能被错误地转换。如果这对您很重要,则您将需要其他时区信息源,例如Noda Time附带的tzdb副本。

还要注意,从DateTimeDateTimeOffset的转换暗示了本地时间,但仅当输入值的.KindDateTimeKind.LocalDateTimeKind.Unspecified时才隐含。如果改为DateTimeKind.Utc,则生成的DateTimeOffset的偏移量将为零。