注意:为了方便起见,使用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年的美国东部标准时区,在美国实行夏令时之前
答案 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副本。
还要注意,从DateTime
到DateTimeOffset
的转换暗示了本地时间,但仅当输入值的.Kind
为DateTimeKind.Local
或DateTimeKind.Unspecified
时才隐含。如果改为DateTimeKind.Utc
,则生成的DateTimeOffset
的偏移量将为零。