【问题标题】:Converting DateTime from specific timezone to UTC - missing hour?将 DateTime 从特定时区转换为 UTC - 缺少小时?
【发布时间】:2013-08-06 11:20:55
【问题描述】:

我无法理解如何正确地将DateTime 转换为不同的时区。

可以说,我想将 DateTime 转换为 EST 中的时间:10:00(军事)到 UTC 中的 DateTime

这是我的尝试:

DateTime unspecified = new DateTime(2013, 8, 15, 10, 0, 0, DateTimeKind.Unspecified);
var utc = TimeZoneInfo.ConvertTime(unspecified, TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time"), TimeZoneInfo.Utc);

...我用DateTimeKind.Unspecified 构造DateTime,因为它既不是UTC,也不是本地时间(它是美国东部标准时间10:00)。然后我将它传递给TimeZoneInfo.ConvertTime,告诉它这是美国东部标准时间的DateTime,我想将其转换为UTC。

由于EST is 5 hours behind of Coordinated Universal Time (UTC) 我希望utc 等于{15.08.2013 15:00:00},但是当我运行上面的代码时,由于某种原因,我得到{15.08.2013 14:00:00}(即时差是4 小时) .

问题是:为什么?这是某种日间节省时间问题吗?如果是这样 - 如何在没有日间节省时间概念的情况下获得这种转换?

【问题讨论】:

  • 是的,夏时制就是这样做的原因。一个不考虑它的简单方法是简单地使用TimeZoneInfoBaseUtcOffsetnew DateTime(2013, 8, 15, 10, 0, 0, DateTimeKind.Unspecified) .Subtract(TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time").BaseUtcOffset); 但是,我不确定在某些特殊情况下是否会搞砸,哪些可能会搞砸。

标签: c# datetime timezone


【解决方案1】:

具有Id"Eastern Standard Time" 的Windows 时区不仅适用于美国东部标准时间。它涵盖了 EST (-5) 和 EDT (-4)。您不会仅从 id 名称中知道它。这有点命名异常,是 Microsoft Windows 时区数据库中的几件棘手的事情之一。请参阅the timezone tag wiki 了解更多信息。

幸运的是,它并不是唯一的数据库。它甚至不是最常用的数据库,它只是 Windows 和 .Net 附带的默认数据库。要使用标准 IANA 时区数据库进行此转换,请使用 Noda Time

DateTimeZone tz = DateTimeZoneProviders.Tzdb["America/New_York"];
LocalDateTime dt = new LocalDateTime(2013, 8, 15, 10, 0, 0);
ZonedDateTime zdt = tz.AtLeniently(dt);
Instant utc = zdt.ToInstant();

还要注意 Noda Time 如何为您提供不会被误解的类型。没有影响行为的Kind。这里的“本地”仅表示一些本地值,而不是您自己的本地时钟。

另请注意,我使用AtLeniently 将日期应用于时区。这是一种在应用时间不明确或无效时进行调整的策略。还有AtStrictly,在这些场景中会抛出异常。或者,您可以创建自己的策略。 TimeZoneInfo 类没有这种级别的控制。

【讨论】:

    【解决方案2】:

    是的,应用了日光节约。见Wikipedia

    遵守标准时使用东部标准时间 (EST) 的地方 时间(秋/冬)比世界协调时间晚 5 小时 (UTC−05:00)。

    东部夏令时 (EDT),在遵守夏令时时 (春季/夏季)比世界协调时间晚 4 小时 (UTC−04:00)。

    转换方法正确。您对 EST 时区的假设是有缺陷的。如果您输入的日期确实是 EST,那么转换是正确的。如果这不符合您的期望,您需要检查输入数据的来源以及实际输入的时区。 如果您正在处理数据库中保存的日期,并且您不再知道什么是正确的,什么不是,那么您就有麻烦了。

    一般来说,使用DateTimeOffset 而不是 DateTime 会更安全,因为它总是将 UTC 时间存储为 DateTime,并将本地时区偏移量存储为其中的附加值。这使得从本地时间确定真正的 UTC 时间变得微不足道。

    【讨论】:

      【解决方案3】:

      您可以轻松地将任何 TimeZone 的任何 DateTime 转换为 UTCDateTime。

      Here is the Example

         string DisplayName = "custom standard name here";
         string StandardName = "custom standard name here"; 
         string YourDate="2013/8/15 10:0:0"; 
         TimeSpan Offset = new TimeSpan(+10, 00, 00);
         TimeZoneInfo TimeZone = TimeZoneInfo.CreateCustomTimeZone(StandardName, Offset, DisplayName, StandardName);
         var RawDateTime = DateTime.SpecifyKind(DateTime.Parse(YourDate), DateTimeKind.Unspecified);
         DateTime UTCDateTime = TimeZoneInfo.ConvertTimeToUtc(RawDateTime, TimeZone);
         Console.WriteLine(UTCDateTime);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-03-21
        • 1970-01-01
        • 2020-06-16
        • 2014-08-12
        • 2011-02-02
        • 2014-07-15
        • 2021-02-14
        • 1970-01-01
        相关资源
        最近更新 更多