.ToUniversalTime()不正确?

Mar*_*rkF 0 c# timezone datetime

    DateTime dt = new DateTime(1972, 4, 24, 0, 0, 0);
    Response.Write("dt: " + dt.ToString("M/d/yyyy h:mm:ss tt") + "<br />");
    Response.Write("dt.Kind: " + dt.Kind.ToString() + "<br />");
    Response.Write("dt.ToUniversalTime(): " + dt.ToUniversalTime().ToString("M/d/yyyy h:mm:ss tt") + "<br />");
Run Code Online (Sandbox Code Playgroud)

显示

dt: 4/24/1972 12:00:00 AM
dt.Kind: Unspecified
dt.ToUniversalTime(): 4/24/1972 7:00:00 AM
Run Code Online (Sandbox Code Playgroud)

这是不正确的。太平洋地区1972年4月24日下午12点实际上是UTC 1972年4月24日上午8点。

我已经通过iOS的内部UTC日期对话和www.timeanddate.com确认了正确的UTC转换,并且UTC时间应该是8 AM。难道我做错了什么?

服务器在“太平洋时间”时区运行,因此ToUniversalTime应该从太平洋时区转换为UTC,因为未指定被视为本地。

And*_*ker 5

如果您使用的不是太平洋标准时间的计算机,则可以使用以下代码查看此行为:

DateTime dt = new DateTime(1972, 4, 24, 0, 0, 0);    
TimeZoneInfo tz = TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time");

Console.WriteLine (TimeZoneInfo.ConvertTimeToUtc(dt, tz));
// 4/24/1972 7:00:00 AM
Run Code Online (Sandbox Code Playgroud)

如果查看navy.mil的夏时制历史,您会注意到以下段落:

1966年的《统一时间法》规定了美国夏令时的开始和结束日期,但允许当地免除遵守该法的规定。该法案规定,夏令时开始于4月的最后一个星期日,结束于10月的最后一个星期日,转换时间为当地时间凌晨2点。

再过一会儿:

1986年通过了一项法律,将夏令时的开始日期更改为从1987年开始的四月的第一个星期日

因此,DST切换直到1987年才在4月的第一个星期日进行,但是由于某种原因,.NET表现得好像是这样。

Timeanddate.com的DST历史似乎是一致的,并将1972年4月30日(4月的最后一个星期日)列为日期时钟向前一小时(至UTC-7)。

微软在1987年之前的DST调整规则似乎是错误的(而且我不是唯一这样认为的人)。

以下是TimeZoneInfoPST的规则:

在此处输入图片说明

基本上,Microsoft忽略了历史规则,而是选择使用那些在1987年生效的规则,直到这些规则存在之前。

本质上,Microsoft的TimeZoneInfo调整规则不正确地处理了您的日期(1972年)。

如果您正在寻找一种可以更好地处理这些时区规则的库,请查看NodaTime,它可以正确处理这种特殊情况:

var pacific = DateTimeZoneProviders.Tzdb["America/Los_Angeles"];

LocalDateTime localDateTime = new LocalDateTime(1972, 4, 24, 0, 0);
ZonedDateTime zonedDateTime = pacific.AtStrictly(localDateTime);

DateTime utcDateTime = zonedDateTime.ToDateTimeUtc();

Console.WriteLine(utcDateTime);
// 4/24/1972 8:00:00 AM
Run Code Online (Sandbox Code Playgroud)