DateTime ToLocalTime失败

时间:2015-05-22 00:34:00

标签: c# mongodb

我正在使用MongoDB数据库。我知道当你将一个DateTime插入Mongo时,它会将它转换为UTC。但我正在进行单元测试,而我的Assert正在失败。

[TestMethod]
public void MongoDateConversion() {
    DateTime beforeInsert = DateTime.Now;
    DateTime afterInsert;

    Car entity = new Car {
        Name = "Putt putt",
        LastTimestamp = beforeInsert
    };

    // insert 'entity'
    // update 'entity' from the database

    afterInsert = entity.LastTimestamp.ToLocalTime();

    Assert.AreEqual(beforeInsert, afterInsert); // fails here
}

我必须遗漏一些明显的东西。当我查看调试器时,我可以看到datetime的匹配,但断言仍然说他们没有(但他们这样做):

Result Message: Assert.AreEqual failed. Expected:<5/21/2015 8:27:04 PM>. Actual:<5/21/2015 8:27:04 PM>.

我在这里做错了什么想法?

修改

我想出了两个可能的解决方案,这两个解决方案都需要我记住做某事(这并不总是最好的依赖......):

一种方法是使用扩展方法截断数据库中出现的任何DateTime:

public static DateTime Truncate(this DateTime dateTime) {
    var timeSpan = TimeSpan.FromMilliseconds(1);
    var ticks = -(dateTime.Ticks % timeSpan.Ticks);
    return dateTime.AddTicks(ticks);
}

另一个,在阅读http://alexmg.com/datetime-precision-with-mongodb-and-the-c-driver/之后,将标记POCO类中的任何DateTime:

public class Car : IEntity {
    public Guid Id { get; set; }

    [BsonDateTimeOptions(Representation = BsonType.Document)]
    public DateTime LastTimestamp { get; set; }
}

3 个答案:

答案 0 :(得分:1)

我猜你的毫秒差异。尝试截断毫秒,如下所示:

DateTime d = DateTime.Now;
d = d.AddMilliseconds(-d.Millisecond);

答案 1 :(得分:1)

您的测试错误(或不一致),因为插入前后总会有几毫秒的差异。您可以将日期时间转换为格式为dd/mm/yy hh:mm:ss的字符串,并在

之前和之后进行比较

答案 2 :(得分:1)

MongoDB将DateTimes存储为自UNIX纪元以来的64位毫秒数。查看此页面:http://alexmg.com/datetime-precision-with-mongodb-and-the-c-driver/

由于.NET的DateTime的分辨率是100纳秒,因此MongoDB几乎肯定会截断你往返的任何DateTime时间。

您有几个选择。

选项1:确保在设置LastTimestamp时或插入记录之前截断LastTimestamp:

English US

这种方法容易出错。设置LastTimestamp的任何人都必须记住要截断它,或者你可以在插入记录之前截断该值,但是你可能需要意外地更改CLR对象。

或者,您可以使用getter / setter,并在每次设置时将LastTimestamp截断为毫秒。但是这可能导致其他一些单元测试进一步失败,因为这个测试失败的原因完全相同。

选项2:如果亚毫秒精度并不重要,只需在断言中加入一些容差:

SELECT ( CASE 
           WHEN ( To_number(Substr(ww1, 0, 4)) = To_number(Substr(ww2, 0, 4)) ) 
         THEN 
           To_number(Substr(ww1, -2)) - To_number(Substr(ww2, -2)) 
           WHEN ( To_number(Substr(ww1, 0, 4)) <> To_number(Substr(ww2, 0, 4)) ) 
         THEN ( 
           ( 
         To_number(Substr(ww1, 0, 4) - To_number(Substr(ww2, 0, 4))) * 53 ) + 
           To_number (Substr(ww1, -2)) ) - To_number(Substr(ww2, -2))
         END ) AS diff 
FROM   weeks;