C# 安全地比较本地和通用日期时间
我刚刚注意到DateTime比较中的一个荒谬缺陷C# 安全地比较本地和通用日期时间,c#,.net,.net-4.0,datetime-comparison,C#,.net,.net 4.0,Datetime Comparison,我刚刚注意到DateTime比较中的一个荒谬缺陷 DateTime d = DateTime.Now; DateTime dUtc = d.ToUniversalTime(); d == dUtc; // false d.Equals(dUtc); //false DateTime.Compare(d, dUtc) == 0; // false 如果一个是DateTimeKind.Local,另一个是DateTimeKind.UTC,则DateTimes上的所有比较操作似乎都无法执行任何类型
DateTime d = DateTime.Now;
DateTime dUtc = d.ToUniversalTime();
d == dUtc; // false
d.Equals(dUtc); //false
DateTime.Compare(d, dUtc) == 0; // false
如果一个是DateTimeKind.Local,另一个是DateTimeKind.UTC,则DateTimes上的所有比较操作似乎都无法执行任何类型的智能转换。除了始终将比较中涉及的日期时间和时间转换为utc时间之外,可靠地比较日期时间是否是更好的方法?经过编辑,我最初的答案部分不正确: 调用
.Equal
或.Compare
时,会在内部比较值.InternalTicks
。这个字段是不相等的,因为它被调整了几个小时以表示世界时间中的时间。您应该这样看:DateTime对象表示未命名时区中的时间,但不是universal time plus时区。时区可以是本地(系统的时区)或UTC。您可能会认为这是缺少DATETIME类。
当转换到另一个时区时,时间是——并且应该——调整的。这可能就是为什么Microsoft选择使用方法而不是属性,以强调转换为UTC时采取的操作
最初我在这里写到,结构是比较的,System.DateTime.Kind
的标志是不同的。事实并非如此:不同的是滴答声的数量:
t1.Ticks == t2.Ticks; // false
t1.Ticks.Equals(t2.Ticks); // false
为了安全地比较两个日期,您可以将它们转换为相同的日期。如果在比较之前将任何日期转换为世界时,您将得到您想要的结果:
DateTime t1 = DateTime.Now;
DateTime t2 = t1;
DateTime.Compare(t1.ToUniversalTime(), t2.ToUniversalTime()); // 0
DateTime.Equals(t1.ToUniversalTime(), t2.ToUniversalTime()); // true
寓意:永远不要比较
日期时间
天真地为了解决这个问题,我创建了自己的DateTime对象(我们称之为SmartDateTime),它包含日期时间和时区。在使用原始日期时间操作符进行比较之前,我覆盖所有操作符,如==并比较并转换为UTC。为什么不将所有日期都设置为UTC?对于与之关联的业务对象,它们将始终为UTC。然而,在整个应用程序的其他地方,当在一个特定的业务对象上使用日期字段时,我必须记住转换为utc时间。这是一个令人讨厌的、难以发现的bug的来源,特别是如果你在一个等于utc的本地时区开发,发现您的产品在发货时或夏时制开始时出现故障。我认为这个故事的寓意是,您应该在应用程序中的任何地方使用任何数据的标准格式(Unicode字符串、UTC日期等)。我支持您对这一荒谬缺陷的看法。MSDN文章()指出DateTime:“表示时间上的一个瞬间,通常表示为一天中的一个日期和时间。”文章作者似乎同意您和我关于这应该如何工作的看法。实施似乎失败了。这就是我计划要做的。最糟糕的是,它与linq to sql绑定,因此我必须将现有的datetime字段设置为私有,并公开我的自定义类的实例,该实例将持久保持为私有datetime…谈谈uglyUgh。您最好在数据库中添加一个TimeZoneInfo字段,并将日期全部存储在UTC中。这就是我一直在做的,只是需要转换任何数据库中使用的每个日期时间有点糟糕comparison@jdc0589:我原来的回答不正确,我更新了它以反映实际的内部情况。有人能为DateTime证明这种行为吗?我想我就是不明白。为什么直接比较不能解释时区?这对我来说似乎有缺陷,我认为这是一个错误