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

标签 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));

由于从夏令时到正常时间的过渡应该发生在 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 with TimeZoneInfo.SupportsDaylightSavingTime set to False. Any TimeZoneInfo.ConvertTime(...) calls using this TimeZoneInfo 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/

相关文章:

c# - LINQ to Entities - 解析/过滤对象集合

c# - 在 C#/.NET 中逐笔更新到烛台/OHLC 数据

.net - Windows 和 .NET 之间的时区是否同步

java - 如何在Java中获取时区小时和分钟?

python - 在python 3中在时区之间转换(格式化相同的时间实例)

unix - 欧洲/伦敦的时区和 BST 问题

c# - ASP.NET MVC 中 _layout.cshtml 中的布局

c# - 为什么 String.Format 会产生歧视?

swift - Swift 中来自服务器的日期

c# - 相关链接自动获得 session ID