我正在使用 MongoDB 数据库。我知道当您将 DateTime 插入 Mongo 时,它会将其转换为 UTC。但是我正在做一个单元测试,我的断言失败了。
[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
}
我一定遗漏了一些明显的东西。当我查看调试器时,我可以看到日期时间匹配,但断言仍然说它们不匹配(但确实如此):
Result Message: Assert.AreEqual failed. Expected:<5/21/2015 8:27:04 PM>. Actual:<5/21/2015 8:27:04 PM>.
有什么想法我在这里做错了吗?
编辑:
我提出了两种可能的解决方案,这两种解决方案都需要我记住做某事(这并不总是最好的依靠...):
一种是使用扩展方法来截断从数据库中出来的任何日期时间:
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; }
}
最佳答案
MongoDB 将 DateTimes 存储为自 UNIX 纪元以来的 64 位毫秒计数。请参阅此页面:http://alexmg.com/datetime-precision-with-mongodb-and-the-c-driver/
由于 .NET 的 DateTime 的分辨率是 100 纳秒,因此 MongoDB 几乎可以肯定会像这样截断您往返的任何 DateTime 时间。
你有几个选择。
选项 1:确保在设置时截断 LastTimestamp,或在插入记录之前截断:
long excessTicks = timestamp.Ticks % 10000;
timestamp= new DateTime(
ticks: timestamp.Ticks - excessTicks,
kind: timestamp.Kind
);
这种方法很容易出错。设置 LastTimestamp 的任何人都必须记住截断它,或者您可以在插入记录之前截断值,但您可能需要意外更改 CLR 对象。
或者,您可以使用 getter/setter 并在每次设置时将 LastTimestamp 截断为毫秒。但这可能会导致其他一些单元测试进一步失败,原因与此测试失败的原因完全相同。
选项 2:如果亚毫秒精度不重要,只需在断言中添加一些容差即可:
TimeSpan delta = beforeInsert - afterInsert;
Assert.IsTrue(Math.Abs(delta.TotalMilliseconds) <= 2);
关于c# - DateTime ToLocalTime 失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30386601/