Mongodb c# 驱动程序和 ISODate
本文关键字:ISODate 驱动程序 Mongodb | 更新日期: 2023-09-27 18:35:15
我有以下测试通过:
namespace MongoDateTest
{
[TestFixture]
public class DateTesting
{
public class TestEntity
{
public string Id { get; set; }
public string StringTest { get; set; }
public DateTime DateTest { get; set; }
}
[Test]
public void MongoDateConversion()
{
const string connectionString = "mongodb://localhost";
var client = new MongoClient(connectionString);
var server = client.GetServer();
var database = server.GetDatabase("test");
var collection = database.GetCollection<TestEntity>("entities");
var entity = new TestEntity {
Id = "1",
StringTest = "Test",
DateTest = new DateTime(2013, 10, 13) //this is the date
};
collection.Save(entity);
var id = entity.Id;
var query = Query<TestEntity>.EQ(e => e.Id, id);
var entityNew = collection.FindOne(query);
Assert.AreEqual(entityNew.Id, entity.Id);
Assert.AreEqual(entity.StringTest, entityNew.StringTest);
//Assert.AreEqual(entity.DateTest,entityNew.DateTest);
// This gives one day error:
// Expected: 2013-10-13 00:00:00.000
// But was: 2013-10-12 22:00:00.000
//Assert.AreEqual(entity.DateTest.ToLocalTime(),entityNew.DateTest.ToLocalTime());
// This gives a 2 hours error.
// Expected: 2013-10-13 02:00:00.000
// But was: 2013-10-13 00:00:00.000
Assert.AreEqual(entity.DateTest, entityNew.DateTest.ToLocalTime());
}
}
}
如果我取消注释任何断言.AreEqual,我会收到一个错误(下面评论)。
保存的实体为:
{
"_id" : "1",
"StringTest" : "Test",
"DateTest" : ISODate("2013-10-12T22:00:00Z")
}
我知道这可能与 ISODate 和 UTC 有关(我在 UTC+1 中),但我有点恼火我的日期在集合中保存时相差一天,并且要求我在任何时候获取一些带有日期的数据时转换为本地时间。
这种行为的原因是什么,有没有办法避免它?
在大多数情况下,您希望将UTC日期时间存储在数据库中,因此您的DateTime应构造为:-
DateTest = new DateTime(2013, 10, 13, 0, 0, 0, DateTimeKind.Utc) //this is the date
有了这个,您注释的第一个单元测试现在通过了。
如果不指定DateTimeKind
,您将听天由命。 MongoDB似乎假设它是本地的,并在数据库中将其转换为UTC。
另请注意,MongoDB DateTime 值的精度低于 .NET DateTime 值。 如果要存储任意 DateTime 值并以它们仍然匹配的方式取回它们,则需要在存储它们之前将它们四舍五入到最接近的毫秒。
如果您确实想存储本地时间,我建议您从 DateTime
切换到 DateTimeOffset
并将其序列化为 UTC 日期时间的长 Tick 值和偏移量值。
请注意,除非存储获取 DateTime 值时计算的偏移量,否则转换为 LocalTime 的 .NET 方法基本上是无用的,因为它们不知道夏令时何时开始,甚至不知道 DateTime 值来自哪个区域。 总体而言,.NET DateTime 处理还有很多不足之处,并且包含许多声称有帮助但实际上没有帮助的误导性方法。
您也可以在模型中执行此操作。公共类测试实体
{
public string Id { get; set; }
public string StringTest { get; set; }
[BsonDateTimeOptions(Kind = DateTimeKind.Utc)]
public DateTime DateTest { get; set; }
}