我无法理解如何正确地将DateTime
转换为不同的时区。
让我们说,我希望将DateTime
与时间:美国东部时间的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);
...我用DateTime
构建DateTimeKind.Unspecified
,因为它既不是UTC,也不是本地时间(美国东部时间10点)。然后我将其传递给TimeZoneInfo.ConvertTime,告诉它在EST中是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小时)。
问题是:为什么?这是某种白天节约时间吗?如果是这样 - 如何在没有白天节省时间的情况下进行此转换?
答案 0 :(得分:1)
Id
"Eastern Standard Time"
的Windows时区不仅适用于EST。它涵盖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
影响行为。 “Local”在这里只是意味着一些本地值,而不是你自己的本地时钟。
另请注意,我使用AtLeniently
将日期应用于时区。这是一种在应用模糊或无效时间时进行调整的策略。还有AtStrictly
,它会在这些场景中抛出异常。或者,您可以创建自己的策略。 TimeZoneInfo
类没有这种控制级别。
答案 1 :(得分:0)
是的,应用了dalylight保存。见Wikipedia
在观察标准时使用东部标准时间(EST)的地方 时间(秋/冬)<协调世界时>后<强> 5小时 (UTC-05:00)。
东部夏令时(EDT),观察夏令时 (春/夏)在协调世界时的后面<强> 4小时 (UTC-04:00)。
转换方法是正确的。你对EST时区的假设是有缺陷的。如果您的输入日期确实是EST,那么转换是正确的。如果这不符合您的期望,您需要检查输入数据的来源以及输入的时区。 如果您正在处理数据库中保存的日期,并且您不知道什么是正确的,哪些不是您遇到麻烦。
一般来说,使用DateTimeOffset而不是DateTime更安全,因为它确实将UTC时间作为DateTime存储,并将本地时区偏移作为其中的附加值存储。这使得从当地时间确定真实的UTC时间变得微不足道。
答案 2 :(得分:0)
您可以轻松地将任何时区的任何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);