【问题标题】:Comparing equal datetimes returns false比较相等的日期时间返回 false
【发布时间】:2013-04-09 22:42:56
【问题描述】:

我有一个关于如何在 C# 中比较/存储日期时间的问题。考虑以下代码:

var createdDate = DateTime.Now;
using (cr = new LanguageDictionaryRepository(ds)) {
    cr.Add(new Sybrin10.Data.DTO.LanguageDictionary() {
        Active = true,
        CreatedDate = createdDate,
        CultureCode = cultureCode,
        Data = new System.Text.UTF8Encoding().GetBytes("Test")
    });
    cr.Save();

    var y = cr.FindBy(x => x.CultureCode == cultureCode && x.CreatedDate == createdDate).FirstOrDefault();
    Assert.IsNotNull(y);

Assert.IsNotNull 由于日期时间检查而失败。我希望,由于 LanguageDictionary 实例是使用变量值创建的,因此两者将相等。这是使用 Telerik.OpenAccess 和 MSSQL 作为数据库层,所以我假设问题出在那儿。谁能告诉我我是否缺少任何东西以及如何正确比较这些值。

编辑:刻度值不同,但我不知道为什么,因为它们都来自同一个变量,我只分配一次。

【问题讨论】:

  • 您确定日期相同吗?比较将考虑小时/分钟/秒/毫秒。
  • 就是这样,刻度值不同,但我不确定为什么它们都来自同一个变量 createdDate。
  • 抱歉,不小心删除了我的评论:/ 刻度有多少不同?这是一个恒定的差异吗?
  • 117 x.CreatedDate 更大。
  • 我已经更新了我的答案,基本上117 没什么区别,因为 Tick 是百万分之一秒。

标签: c# datetime


【解决方案1】:

尝试使用DateTime.Equals(x.CreatedDate, createdDate),它可能会有所帮助。

除此之外,正确的DateTime 比较是一个非常复杂的主题,包括时区、偏移量、UTC、当地时间等等。我一点也不会对简单的== 在两个看似相同的日期之间进行比较以返回 false 感到惊讶。

如果Ticks 值在写入和读取时不同,您可能会遇到DateTimeKind 问题,您正在将DateTimeKind.Local 写入数据库,但返回DateTimeKind.Unspecified

另一个选项可能是(如果差异足够小)数据库中的 DateTime 字段不足以存储与 .net DateTime 相同的毫秒数:

单个滴答表示一百纳秒或百万分之一秒。一毫秒内有 10,000 个滴答声。

根据您的数据存储,可能没有这么详细。您的DateTime 值并非来自同一来源,一个是从内存中读取的,另一个是从数据库中读取的。

【讨论】:

  • 在这种情况下,比较日期的字符串表示是否有效?
  • 如果您只想取回您创建的记录,请参阅 Teleriks How to: Insert Objects。保存后会回读创建的主键。
  • 实际上,我将创建一个 DateTime 类的扩展,以便在没有刻度的情况下进行比较,因为我看到这再次出现。谢谢你的回答,让我明白了很多。
【解决方案2】:

SqlServer 以(大约)3 毫秒为增量存储datetime

日期时间值四舍五入为 0.000、0.003 或 0.007 秒的增量

因此,通过数据库的 DateTime 往返可能会延迟几毫秒。

所以你不应该测试“完全相等”,而应该测试“足够接近”

var y = cr.FindBy(x => x.CultureCode == cultureCode && 
                    x.CreatedDate >= createdDate.AddMilliseconds(-5) && 
                    x.CreatedDate <= createdDate.AddMilliseconds(5))
     .FirstOrDefault();

【讨论】:

  • 我不知道这一点,感谢您指出,我会赞成,但您的代码示例在现实中不是很实用。现在如果你把它作为一个扩展,现在我们正在讨论
  • 如果您正在寻找更短的符号,您可以使用(x.CreatedDate - createdDate).Milliseconds &lt; 4
  • @DdW - 你需要在它周围添加一个Math.Abs,因为你可以从比较中得到负值(当然总是
【解决方案3】:

我认为在存储数据时使用 DateTime.UtcNow 可能会更好,这样您就不必担心夏令时问题等。然后您可以稍后使用您想要的文化显示它选择。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-21
    • 2021-04-15
    • 1970-01-01
    • 2016-08-05
    • 2020-08-20
    相关资源
    最近更新 更多