1

我在理解如何DateTime正确转换为不同的时区时遇到问题。

可以说,我想将DateTime时间转换为:东部标准时间 10:00(军事)到DateTimeUTC。

这是我尝试的:

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

...我DateTime用构建DateTimeKind.Unspecified,因为它既不是 UTC,也不是本地时间(它是 10:00 EST)。然后我将它传递给TimeZoneInfo.ConvertTime,告诉它这是DateTime在 EST 中,我想将它转换为 UTC。

由于EST比协调世界时 (UTC) 晚5 小时,我希望utc等于{15.08.2013 15:00:00},但是当我在上面运行代码时,出于某种原因,得到{15.08.2013 14:00:00}(即时差为4 小时)。

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

4

3 回答 3

1

具有Idof的 Windows 时区"Eastern Standard Time"不仅适用于 EST。它涵盖了 EST (-5) 和 EDT (-4)。您不会仅从 id 名称中知道它。这有点命名异常,是 Microsoft Windows 时区数据库中的几件棘手的事情之一。有关更多信息,请参阅时区标记 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没有这种级别的控制。

于 2013-08-06T17:57:27.547 回答
0

是的,应用了日光节约。见维基百科

在观察标准时间(秋季/冬季)时使用东部标准时间 (EST) 的地方比协调世界时 (UTC-05:00) 晚5 小时。

东部夏令时 (EDT),当观察夏令时(春季/夏季)时,比协调世界时 (UTC−04:00) 晚4 小时。

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

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

于 2013-08-06T11:40:08.623 回答
0

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

这是示例

   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);
于 2019-03-27T15:21:55.917 回答