.ToUniversalTime()不正确?

时间:2015-04-30 01:30:12

标签: c# datetime timezone

    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 />");

显示器

dt: 4/24/1972 12:00:00 AM
dt.Kind: Unspecified
dt.ToUniversalTime(): 4/24/1972 7:00:00 AM

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

我已通过iOS的内部UTC日期对话和www.timeanddate.com确认了正确的UTC转换,UTC时间应为早上8点。我做错了吗?

服务器正在&#34; Pacific Time&#34; timezone所以ToUniversalTime应该从太平洋时区转换为UTC,因为Unspecified被视为Local。

1 个答案:

答案 0 :(得分:4)

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

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

如果您查看navy.mil's history of daylight saving time,您会注意到以下段落:

  

1966年的统一时间法案提供了日期的标准化   在美国开始和结束白天时间,但允许在当地   豁免遵守。 该法案规定了白天时间   从4月的最后一个星期日开始,到最后一个星期天结束   10月,转换发生在当地时间凌晨2点。

然后一会儿:

  

1986年,通过了一项法律,改变了日光的开始日期   从1987年开始到4月的第一个星期天

因此DST切换不是4月的第一个星期日,直到1987年,但由于某些原因,.NET的行为就好像是。

Timeanddate.com's history of DST seems to agree,并列出1972年4月30日(4月的最后一个星期日),因为日期时钟转了一小时(到UTC-7)。

微软在1987年之前的DST调整规则似乎是错误的(and I'm not the only one who thinks so)。

这里有TimeZoneInfo列出的PST规则:

enter image description here

基本上,微软忽视了历史规则,并选择使用1987年生效的规则来规定在这些规则存在之前发生的日期。

基本上,您的日期(1972年)被微软的TimeZoneInfo调整规则错误处理。

如果您正在寻找能够更好地处理这些类型的时区规则的库,请查看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