我有两个日期属性,它们与我从一个对象映射到另一个对象完全相同。如果我将它们比作如下,则返回false:
if(obj1.d1 == obj2.d1)
{
}
它们都是{01/06/2011 15:44:32}
。
我无法使用DateTime.Compare
,因为它们可以为空。比较可空日期的最佳方法是什么?
答案 0 :(得分:7)
检查这些日期的实际滴答,它们可能会有所不同。请注意,DateTime
记录100 ns间隔作为其最小单位。格式化DateTime
。
答案 1 :(得分:2)
您可以使用Nullable.Compare<T>()
方法比较可空对象,包括可以为空的日期。
if(Nullable.Compare(obj1.d1, obj2.d1) == 0)
{
}
答案 2 :(得分:1)
这应该有效,请检查:
var now = DateTime.Now;
DateTime? d1 = now;
DateTime? d2 = now;
Console.WriteLine(d1 == d2); // Output: True
我认为它们实际上不完全相同,即它们以毫秒或刻度不同。
答案 3 :(得分:1)
正如其他答案所示,默认比较器对于可以为空的DateTime对象可以正常工作。您已在评论中询问如何比较日期的圆形形式。你会想要这样的东西:
if (dt1.EqualsRounded(dt2))
以下是您需要执行此操作所需的所有代码。它完全支持可空和不可为空的DateTimes。它实现了IComparer<T>
和IEqualityComparer<T>
,因此您也可以在排序列表时使用它(例如)。对于像上面这样的简单情况,存在扩展方法,并且存在提供不同舍入间隔的重载。如果没有指定,则默认为舍入到最接近的整秒。享受!
public static class DateTimeExtensions
{
public static DateTime RoundToNearestInterval(this DateTime dateTime, TimeSpan interval)
{
// Adapted from http://stackoverflow.com/questions/1393696/c-rounding-datetime-objects
// do the rounding
var intervalTicks = interval.Ticks;
var ticks = (dateTime.Ticks + (intervalTicks / 2) + 1) / intervalTicks;
var totalTicks = ticks * intervalTicks;
// make sure the result is not to low
if (totalTicks < 0)
totalTicks = 0;
// make sure the result is not to high
const long maxTicks = 0x2bca2875f4373fffL; // DateTime.MaxTicks
if (totalTicks > maxTicks)
totalTicks = maxTicks;
// return the new date from the result
return new DateTime(totalTicks, dateTime.Kind);
}
public static bool EqualsRounded(this DateTime x, DateTime y)
{
return x.EqualsRounded(y, TimeSpan.FromSeconds(1));
}
public static bool EqualsRounded(this DateTime x, DateTime y, TimeSpan interval)
{
var comparer = new RoundedDateTimeComparer(interval);
return comparer.Equals(x, y);
}
public static bool EqualsRounded(this DateTime? x, DateTime? y)
{
return x.EqualsRounded(y, TimeSpan.FromSeconds(1));
}
public static bool EqualsRounded(this DateTime? x, DateTime? y, TimeSpan interval)
{
var comparer = new RoundedDateTimeComparer(interval);
return comparer.Equals(x, y);
}
public static int CompareRounded(this DateTime x, DateTime y)
{
return x.CompareRounded(y, TimeSpan.FromSeconds(1));
}
public static int CompareRounded(this DateTime x, DateTime y, TimeSpan interval)
{
var comparer = new RoundedDateTimeComparer(interval);
return comparer.Compare(x, y);
}
public static int CompareRounded(this DateTime? x, DateTime? y)
{
return x.CompareRounded(y, TimeSpan.FromSeconds(1));
}
public static int CompareRounded(this DateTime? x, DateTime? y, TimeSpan interval)
{
var comparer = new RoundedDateTimeComparer(interval);
return comparer.Compare(x, y);
}
}
public class RoundedDateTimeComparer :
IComparer<DateTime>, IComparer<DateTime?>,
IEqualityComparer<DateTime>, IEqualityComparer<DateTime?>
{
private readonly TimeSpan _interval;
public RoundedDateTimeComparer(TimeSpan interval)
{
_interval = interval;
}
public int Compare(DateTime x, DateTime y)
{
var roundedX = x.RoundToNearestInterval(_interval);
var roundedY = y.RoundToNearestInterval(_interval);
return roundedX.CompareTo(roundedY);
}
public int Compare(DateTime? x, DateTime? y)
{
return x.HasValue && y.HasValue ? Compare(x.Value, y.Value) : (y.HasValue ? 1 : (x.HasValue ? -1 : 0));
}
public bool Equals(DateTime x, DateTime y)
{
var roundedX = x.RoundToNearestInterval(_interval);
var roundedY = y.RoundToNearestInterval(_interval);
return roundedX.Equals(roundedY);
}
public bool Equals(DateTime? x, DateTime? y)
{
return x.HasValue && y.HasValue ? Equals(x.Value, y.Value) : x.Equals(y);
}
public int GetHashCode(DateTime obj)
{
var rounded = obj.RoundToNearestInterval(_interval);
return rounded.GetHashCode();
}
public int GetHashCode(DateTime? obj)
{
return obj.HasValue ? GetHashCode(obj.Value) : 0;
}
}
答案 4 :(得分:0)
在使用.Compare
之前,你不能检查它们是否为空吗?