2

我试图在 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:00 到 3:00 的时间会是模棱两可的。但是在 1:54 运行代码的结果是:

时区是:(UTC+01:00) 布鲁塞尔、哥本哈根、马德里、巴黎
时区 id 是:浪漫标准时间
现在的时间戳:2013-10-27 01:54
更改规则说:03:00
是 dst: False
是它模棱两可:真

我可能会遗漏一些东西。我希望 dst 是真的,而模棱两可是假的,但情况恰恰相反。

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

4

1 回答 1

0

您应该阅读这篇博文,其中详细描述了 Windows 注册表设置如何受时区选择和“自动调整...”复选框的影响。它还描述了如何TimeZoneInfo使用这些设置。具体来说,它指出:

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

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

如果您在服务器上运行代码,您可能应该将服务器的时区设置为 UTC。这将使 Windows 不必为过渡更新计算机的 bios,并让来自其他服务器的本地时间戳全部对齐。

关于您的代码,请意识到DateTime.Nowhas的结果.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 时刻,以便确定它是否模棱两可。如果您深入研究 .Net 源代码(反编译或符号源)DateTime.IsAmbiguousTime(),您会发现它使用TimeZoneInfo.ConvertTime(),当未选中该框时,它(根据前面的引用)不考虑 DST,从而使结果不正确(本质上休息 1 小时)。

您还应该查看 MSDN 注释TimeZoneInfo.IsAmbiguousTime,其中描述了Kind输入的 影响输出结果的方式。

于 2013-05-30T17:35:42.897 回答