几周前,即2016年3月27日,英国的时钟向前移动了一个小时。在01:00,时钟“跳”到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?
因此,这里唯一的问题是:
为什么DateTime类型不考虑DST?
因为那是DateTime
结构的设计方式。
从MSDN文档:
时区之间的转换操作(例如,UTC与本地时间之间,或一个时区与另一个时区之间)的转换操作考虑了夏令时,但算术和比较操作没有考虑。
.NETDateTime
仅跟踪两个逻辑值,Ticks
而Kind
。在内部,出于性能和兼容性的原因,将它们合并为单个64位整数,但是您可以将它们视为两个单独的值。
Ticks
自纪元值以来跟踪100纳秒间隔的数量0001-01-01 00:00:00
。
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截然不同,Java和JavaScript的Date
对象跟踪的时间间隔为自1970-01-01 00:00:00 UTC
纪元以来的毫秒数。它始终是UTC,.NET可能存在也可能没有。
有多种方法可以解决此问题。到目前为止,最好的办法是使用更加合理的API,该API由Noda Time开源库提供。但是,如果只想使用.NET内置的功能,则可以考虑使用该DateTimeOffset
结构。不同于DateTime
,它会跟踪其与UTC的偏移量,并在进行数学运算时将其考虑在内。
您仍然必须使用来检查输入是否无效TimeZoneInfo.IsInvalidTime
。.NET没有内置的API会在解析时在无效时间内抛出异常。你会,但是,发现在转换功能TimeZoneInfo
,如ConvertTimeToUtc
意志,如果你在一个无效的时间源的时区传递的确抛出异常。
您还应该检查TimeZoneInfo.IsAmbiguousTime
,因为在回退过渡期间给定的值出现了两次,例如2016-10-30 01:30
在英国,.NET将始终选择标准时间偏移。虽然这乍看起来似乎是正确的,但请考虑到日光实例实际上首先发生-这通常是大多数现实世界场景中所需的行为(无论如何,根据我的经验)。
此外,关于Java代码,如果还没有,则应考虑使用Java 7及更低版本的Joda Time或java.time
Java 8内置的Java。您会发现它们与前面提到的Noda Time非常相似。
最后,我将添加自己非常有根据的断言,即DateTime
结构的设计在多种方面违反了SRP。特别DateTimeKind
是一种可憎的-恕我直言。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句