2016年东部标准时间的夏令时于2016年3月13日凌晨2点开始。此时时钟设置回到凌晨1点,使凌晨2点无效。
此代码块报告dateTime2 var。
的凌晨2点的错误TimeZoneInfo timeZoneInfo1;
timeZoneInfo1 = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
var dateTime1 = TimeZoneInfo.ConvertTime(new DateTime(2016, 3, 13, 1, 0, 0), timeZoneInfo1);
var dateTime2 = TimeZoneInfo.ConvertTime(new DateTime(2016, 3, 13, 2, 0, 0), timeZoneInfo1); //Reports invalid date error
var dateTime3 = TimeZoneInfo.ConvertTime(new DateTime(2016, 3, 13, 3, 0, 0), timeZoneInfo1);
但是,在下面的时区"太平洋SA标准时间"示例中,1990年的夏令时从10/13/1990 @ 11pm开始。这应该使dateTime4 10/13/1990 @ 11pm成为无效的日期/时间。
相反,dateTime4作为有效日期/时间返回。
此外,dateTime5将在10/14/1990 @ 1am返回,自动跳过午夜时段。
并且dateTime6在我预期的时候返回到10/14/1990 @ 2am而不是凌晨1点。
TimeZoneInfo timeZoneInfo2;
timeZoneInfo2 = TimeZoneInfo.FindSystemTimeZoneById("Pacific SA Standard Time");
var dateTime4 = TimeZoneInfo.ConvertTime(new DateTime(1990, 10, 13, 23, 0, 0), timeZoneInfo2); //10-14-1990@11pm
var dateTime5 = TimeZoneInfo.ConvertTime(new DateTime(1990, 10, 14, 0, 0, 0), timeZoneInfo2); //10-14-1990@1am
var dateTime6 = TimeZoneInfo.ConvertTime(new DateTime(1990, 10, 14, 1, 0, 0), timeZoneInfo2); //10-14-1990@2am
TimeZoneInfo.ConvertTime的两种工作方式是什么原因?
我正在使用VS2010。
答案 0 :(得分:4)
一些事情:
Pacific SA Standard Time
是具有英文显示名称(UTC-03:00) Santiago
的Windows时区的ID。那是智利的圣地亚哥。
Windows中此区域最早的条目是2007年。它没有1990年的数据,因此错误地假设2007之前的任何内容与2007年相同。通常,Microsoft时区没有广泛的历史。
智利每年都有不同的DST日期。 See here for year-to-year details from that period
In 1990, DST started on September 16th at 12:00 AM。从12:00到凌晨1:00的小时被跳过。根据您的建议,不是10月13日晚上11点到中午12:00。
如果历史准确性对您的应用程序很重要,请不要使用Windows时区标识符或TimeZoneInfo
类。他们不能胜任这项特殊任务。相反,请使用IANA标识符(例如America/Santiago
或America/New_York
),并使用Noda Time。使用Noda Time还有许多其他优点。
要回答最后两个问题,dateTime5
和dateTime6
是在未指定DateTimeKind
的情况下创建的,因此默认情况下为DateTimeKind.Unspecified
。然后,当您调用ConvertTime
函数时,根据备注in the MSDN,假定该值来自您的本地时区。
为清楚起见,您的代码正在将这些日期从本地时区转换为您指定的时区。
因此,如果这些日期在您的本地时区(无论可能是什么)中有效,那么它们确实可以被转换,并且不会抛出异常。如果结果是一个小时不同,那么这意味着您当地的时区距离Windows认为圣地亚哥当时的时间还有一小时。