我正在尝试在 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));
由于从夏令时到正常时间的过渡应该发生在 3:00,我怀疑从 2:00 到 3:00 的时间是不明确的。 但是在 1:54 运行代码的结果是:
Timezone is: (UTC+01:00) Brussels, Copenhagen, Madrid, Paris
Timezone id is: Romance Standard Time
Timestamp right now: 2013-10-27 01:54
Rule for change says: 03:00
Is it dst: False
Is it ambiguous:True
我可能遗漏了什么。 我希望 dst 为真而 ambiguous 为假,但事实恰恰相反。
很难保持概览,但为什么我会看到这种行为?
最佳答案
你应该阅读 this blog post ,其中详细描述了 Windows 注册表设置如何受时区选择和“自动调整...”复选框的影响。它还描述了 TimeZoneInfo
如何使用这些设置。具体来说,它指出:
When daylight saving time is disabled for the local time zone,
TimeZoneInfo.Local
will return a TimeZoneInfo object withTimeZoneInfo.SupportsDaylightSavingTime
set to False. AnyTimeZoneInfo.ConvertTime(...)
calls using thisTimeZoneInfo
instance will not take daylight saving time into account.
恕我直言,没有充分的理由清除该复选框并禁用夏令时。它将计算机的时钟置于人工现实中。
如果您在服务器上运行代码,您可能应该将服务器的时区设置为 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()
,其中(根据较早的引述)在未选中该框时不考虑夏令时,因此导致结果不正确(基本上减少了 1 小时)。
您还应该查看 TimeZoneInfo.IsAmbiguousTime
的 MSDN 注释,它描述了输入的 Kind
如何影响输出结果。
关于c# - TimeZoneInfo 在浪漫标准时间需要前一小时不明确,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16838568/