几周前,2016年3月27日,英国的钟表前进了一个小时。凌晨1点,时钟跳了起来。前进到02:00
http://www.timeanddate.com/time/dst/events.html
这意味着" 2016年3月27日,01:30",是无效的日期时间,即它不代表实际发生的时间'。
当Java日期时间解析器无法理解我们传递给它的时间时,这最近引起了我们的注意。但是,C#DateTime似乎根本没有任何问题。
DateTime dt = DateTime.Parse("2016-03-27 01:30:00");
bool invalid = TimeZoneInfo.Local.IsInvalidTime(dt);
虽然invalid
已正确设置为true
,但DateTime
似乎没有任何问题存储它。
此外,以下声明:
diff = new DateTime(2016, 3, 27, 2, 30, 0) - new DateTime(2016, 3, 27, 0, 30, 0);
导致TimeSpan代表2小时,这是不正确的。
为什么DateTime类型不考虑DST?
答案 0 :(得分:2)
所以,这里唯一的问题是:
为什么DateTime类型不考虑DST?
因为这就是DateTime
结构的设计方式。
时区之间的转换操作(例如UTC与本地时间之间或一个时区之间的转换操作)会考虑夏令时,但算术和比较操作则不会。
.NET的DateTime
仅跟踪两个逻辑值,Ticks
和Kind
。在内部,出于性能和兼容性原因,它们合并为一个64位整数,但您可以将它们视为两个单独的值。
Ticks
跟踪自0001-01-01 00:00:00
的纪元值以来100纳秒间隔的数量。
Kind
跟踪Ticks
是用于表示UTC时间,计算机本地时区或其他某些未指定时区的元数据。
与DateTime
一起使用的每个函数都应该考虑Kind
。框架中的许多人都这样做。有些人没有。许多其他图书馆,甚至一些与时间有关的图书馆,都完全忽视它。
当您致电DateTime.Parse("2016-03-27 01:30:00")
时,Kind
设置为Unspecified
,因为没有上下文。您提供的值不一定在任何特定时区,因此0001-01-01 00:00:00
纪元日期也不一定。换句话说,您可以将其视为未固定到UTC或任何DST规则的任何偏移的日期和时间。
请注意,这与Java和JavaScript有很大不同,其中Date
对象跟踪自1970-01-01 00:00:00 UTC
时代以来的毫秒数。它总是 UTC,其中.NET可能是也可能不是。
有多种方法可以解决这个问题。到目前为止最好的是使用更合理的API,它由Noda Time开源库提供。但是,如果您只想使用.NET内置的功能,请考虑使用DateTimeOffset
结构。与DateTime
不同,它跟踪其与UTC的偏移量,并在进行数学运算时将其考虑在内。
您仍然需要检查TimeZoneInfo.IsInvalidTime
输入是否无效。 .NET内置的API不会在解析时为无效时间抛出异常。但是,如果您为源时区传入无效时间,则会发现TimeZoneInfo
上的转换函数(例如ConvertTimeToUtc
)确实会引发异常。
您还应该检查TimeZoneInfo.IsAmbiguousTime
,因为在两次发生的回退转换期间给出了一个值,例如英国的2016-10-30 01:30
,.NET将始终选择标准时间偏移。虽然这可能起初看起来是正确的,但请考虑 daylight 实例首先实际发生 - 这通常是大多数现实场景中的理想行为(无论如何都来自我的体验)。
除此之外,关于您的Java代码,如果您尚未考虑,则应考虑将Joda Time用于Java 7及更低版本,或者将java.time
用于Java 8中。您将找到它们与前面提到的Noda Time非常相似。
最后,我将添加我非常自以为是的断言,DateTime
结构的设计以多种方式违反SRP。特别是,DateTimeKind
是令人厌恶的 - 恕我直言。
答案 1 :(得分:1)
我知道这很旧,但是我碰到了它,并认为其他人可能会对此线程的添加有所帮助。尽管Matt Johnson-Pint给出的答案是全面的,并且确实非常有用,但是有一种简单的方法可以实现对DateTime的必要“调整”,以显示当前的本地时间-我认为这是对实际问题的回答:
fn.bind
在英国BST中,这给出了正确的结果。
有用的链接here
答案 2 :(得分:0)
DateTime具有Kind属性,指示它是本地时间还是UTC或未指定。您的解析格式不允许它设置此类,因此它将是未指定的。我认为您需要将其设置为允许它正确处理DST。
通常,您以UTC格式处理DateTimes,然后在需要向用户显示以解决此问题时转换为本地DateTime。
答案 3 :(得分:0)
我猜微软决定为您提供使用IsInvalidTime方法自行管理无效日期的灵活性。
如果您的申请要求日期有效,那么您应该检查时间是否有效。
答案 4 :(得分:0)
Azure Web Apps具有很好的默认设置,可用于在Azure界面或Visual Studio中更改此设置。 这里有一个很棒的博客,向您展示了如何做: https://www.jasongaylord.com/blog/tip-changing-an-azure-app-service-time-zone