DateTime比较忽略种类?

lak*_*tak 9 c# datetime utc

DateTime d1=new DateTime(2015, 1, 1, 0, 0, 0, DateTimeKind.Utc);
DateTime d2=new DateTime(2015, 1, 1, 0, 0, 0, DateTimeKind.Local);
Console.WriteLine(d1==d2);           // prints true
Console.WriteLine(d1<d2);            // prints false
Console.WriteLine(d1.CompareTo(d2)); // prints 0
Console.WriteLine(d1.ToUniversalTime()==d2.ToUniversalTime()); // prints false
Run Code Online (Sandbox Code Playgroud)

对我来说这看起来像个错误,如果没有让我感到惊讶.

我是否必须为每次比较调用ToUniversalTime(),还是有更好的选择?

你如何避免因忘记调用ToUniversalTime()或因DateTimeKind.Unspecified而得到错误结果等陷阱?

toa*_*akz 7

MSDN文档非常清楚,DateTimeKind使用Equality运算符时不会将其考虑在内.

Equality运算符通过比较它们的滴答数来确定两个DateTime值是否相等.在比较DateTime对象之前,请确保对象表示同一时区中的时间.您可以通过比较Kind属性的值来完成此操作.

MSDN - DateTime.Equality运算符

您可以编写自己的扩展方法来包含DateTimeKind比较:

public static bool EqualsWithKind(this DateTime time, DateTime other)
{
      return time.Kind == other.Kind &&
             time == other;
}
Run Code Online (Sandbox Code Playgroud)

考虑到Panagiotis KanavosJames Thorpe关于DateTimeOffset以下方面的评论:

如果保证偏移与本地偏移相同,则使用.

public static bool EqualsWithTimezone(this DateTime time, DateTime other)
{
      return new DateTimeOffset(time) == new DateTimeOffset(other);
}
Run Code Online (Sandbox Code Playgroud)

如果偏差不保证相同,请使用:

public static bool EqualsInclTimezone(this DateTime time, TimeSpan timeOffset, DateTime other, TimeSpan otherOffset)
{
      return new DateTimeOffset(time, timeOffset) == new DateTimeOffset(other, otherOffset);
}
Run Code Online (Sandbox Code Playgroud)

  • 警惕那种扩展方法 - 这只是保证它们是同一时间和同一种类.即使种类不同,它们可能仍然是同一时间.应该在这里使用`DateTimeOffset`. (3认同)