TimeZoneInfo在浪漫标准时间需要前一小时不明确

时间:2013-05-30 14:14:50

标签: c# timezone

我正在尝试在C#应用程序中控制夏令时,而不是让Windows执行此操作。 (我不会在这里说出原因)。

所以我在日期和时间设置(Windows7)中删除了“自动调整夏令时”复选标记

为了证明我所面临的问题,我编写了这段小代码。

TimeZoneInfo tzi = TimeZoneInfo.FindSystemTimeZoneById(TimeZoneInfo.Local.Id);
                                                    // "Romance Standard Time"
var rule = tzi.GetAdjustmentRules()[0];

System.Globalization.CultureInfo.CurrentCulture.ClearCachedData();
var timestampToWorkOn = DateTime.Now; 
Console.WriteLine("Timezone is: " + tzi.ToString());
Console.WriteLine("Timezone id is: " + tzi.Id);
Console.WriteLine("Timestamp right now: " + timestampToWorkOn.ToString("yyyy-MM-dd HH:mm"));
Console.WriteLine("Rule for change says: " + rule.DaylightTransitionEnd.TimeOfDay.ToString("HH:mm"));
Console.WriteLine("Is it dst: " + tzi.IsDaylightSavingTime(timestampToWorkOn));
Console.WriteLine("Is it ambiguous:" + tzi.IsAmbiguousTime(timestampToWorkOn));

由于从dst到正常时间的过渡应该发生在3:00,我怀疑从凌晨2点到凌晨3点的时间是不明确的。 但是在1:54运行代码的结果是:

  

时区是:(UTC + 01:00)布鲁塞尔,哥本哈根,马德里,巴黎
  时区ID是:浪漫标准时间
  时间戳现在:2013-10-27 01:54
  变更规则说:03:00
  它是dst:False
  这是不明确的:真的

我可能会遗漏一些东西。 我希望dst是真实的,模糊不清的,但这是相反的方式。

很难保持概述,但为什么我会看到这种行为?

1 个答案:

答案 0 :(得分:0)

您应该阅读this blog post,其中详细说明了Windows注册表设置如何受时区选择和“自动调整...”复选框的影响。它还介绍了TimeZoneInfo如何使用这些设置。具体来说,它声明:

  

如果禁用本地时区的夏令时,TimeZoneInfo.Local将返回一个Time TimeZoneInfo.SupportsDaylightSavingTime设置为False的TimeZoneInfo对象。使用此TimeZoneInfo.ConvertTime(...)实例的任何TimeZoneInfo次呼叫都不会将夏令时考虑在内。

恕我直言,没有充分的理由清除该复选框并禁用夏令时。它将计算机的时钟置于人为的现实中。

如果您在服务器上运行代码,则应该将服务器的时区设置为UTC。这将使Windows无需更新计算机的BIOS以进行转换,并且可以让其他服务器的本地时间戳排成一行。

关于您的代码,请注意DateTime.Now的结果为.Kind == DateTimeKind.Local,并且与您之前使用的时区无关。您恰好报告了本地时区,但如果您使用的是其他时区,则代码将不正确。

当您获得调整规则时,您假设当地时区将有一个。有些(如亚利桑那州)没有任何DST,因此它们没有调整规则,并且您获得了索引超出范围的异常(因为[0])。

另外,只是挑剔但是,

// This line is self redundant.
TimeZoneInfo tzi = TimeZoneInfo.FindSystemTimeZoneById(TimeZoneInfo.Local.Id);

// It can be reduced to:
TimeZoneInfo tzi = TimeZoneInfo.Local;

但真正的问题是因为你关闭了“调整DST”选项,所以DateTime没有被转换为正确的UTC时刻,以便确定它是否含糊不清。如果你深入研究DateTime.IsAmbiguousTime()的.Net源代码(反编译或符号源),你会发现它使用TimeZoneInfo.ConvertTime(),它(根据前面的引用)在框中没有考虑DST未经检查,从而使结果不正确(基本上是1小时)。

您还应查看TimeZoneInfo.IsAmbiguousTime的MSDN说明,其中描述了输入的Kind如何影响输出结果。