【问题标题】:TimeZoneInfo Ambiguous one hour before needed for Romance Standard TimeTimeZoneInfo 浪漫标准时间前一小时不明确
【发布时间】:2013-05-26 04:05:05
【问题描述】:

我试图在 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 是真的,而模棱两可是假的,但事实恰恰相反。

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

【问题讨论】:

  • 选择夏令时更改的确切日期无疑是问题的一部分。加上“我自己做”的角度和 UTC+1 偏移量,可以任意增加一个小时的问题。只在 UTC 工作,让痛苦停止。
  • 但目标是控制windows的时间。包括 dst 转换。如果我想在纯 utc 中工作,并且想要达到控制时间转换的目标,我需要有一个包含所有时区所有规则的数据库......并维护它。我想我可能想仔细看看野田时间。 ....
  • 您是否尝试创建 Iversen 标准时间?这实际上是可能的,TimeZoneInfo.CreateCustomTimeZone()。说服其他程序使用它很可能是个问题。
  • 我不是。基本上是因为它需要控制带有增强型写入文件管理器的 Windows 嵌入式 pc 驱动器。所以没有任何东西被提交到 c 驱动器,因此每次转换后 windows 启动时,它认为它需要调整时间。一次又一次。最终结果是每次启动 pc 时时间会偏移一小时。所以我必须自己控制它并将当前的dst状态存储到d:驱动器
  • 我不得不说,一百年后我都不会猜到这是您要解决的实际问题。修补 TimeZoneInfo 永远不会让您接近解决方案。在 superuser.com 上提问,解释您要解决的真正问题。

标签: c# timezone


【解决方案1】:

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

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

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

如果您在服务器上运行代码,您可能应该将服务器的时区设置为 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 如何影响输出结果。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-05-07
    • 2016-07-06
    • 2015-01-22
    • 2019-11-30
    • 2011-06-17
    • 1970-01-01
    • 2012-06-20
    • 2022-01-05
    相关资源
    最近更新 更多