System.DateTimeOffset 个实例报告了 1883 年 11 月 19 日之前日期的令人惊讶的 UTC 偏移
Surprising UTC offset reported by System.DateTimeOffset instances for dates before 19 Nov 1883
注意:为方便起见,使用 PowerShell 来演示行为,但问题是关于 System.DateTimeOffset
.NET 类型的行为。
注意:正如 Matt Johnson 指出的那样,有问题的行为 只发生在 类 Unix 平台 (macOS, Linux,使用 .NET Core)。
看起来,当 System.DateTimeOffset
转换本地日期时,生成的 时区偏移量(与 UTC 的偏移量)与 1883 年 11 月 19 日之前的日期不同。
考虑以下 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,重点补充:
[...] had brought the US railway companies to an agreement which led to standard railway time being introduced at noon on 18 November 1883 across the nation.
谁能证实这一点并提供更多信息?
为什么偏移量改变了 3 分钟?
Searching for 1883
in the entire .NET documentation yields just the following, passing reference:
[...] the U.S. Eastern Standard Time zone from 1883 to 1917, before the introduction of daylight saving time in the United States
在类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
将具有零偏移量。
注意:为方便起见,使用 PowerShell 来演示行为,但问题是关于 System.DateTimeOffset
.NET 类型的行为。
注意:正如 Matt Johnson 指出的那样,有问题的行为 只发生在 类 Unix 平台 (macOS, Linux,使用 .NET Core)。
看起来,当 System.DateTimeOffset
转换本地日期时,生成的 时区偏移量(与 UTC 的偏移量)与 1883 年 11 月 19 日之前的日期不同。
考虑以下 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,重点补充:
[...] had brought the US railway companies to an agreement which led to standard railway time being introduced at noon on 18 November 1883 across the nation.
谁能证实这一点并提供更多信息?
为什么偏移量改变了 3 分钟?
Searching for 1883
in the entire .NET documentation yields just the following, passing reference:
[...] the U.S. Eastern Standard Time zone from 1883 to 1917, before the introduction of daylight saving time in the United States
在类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.
另请注意,本地时间隐含在从 DateTime
到 DateTimeOffset
的转换中,但仅当输入值的 .Kind
为 DateTimeKind.Local
或 DateTimeKind.Unspecified
时.相反,如果它是 DateTimeKind.Utc
,则结果 DateTimeOffset
将具有零偏移量。