6

我有以下通过的测试:

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());
        }
    }
 }

如果我取消对任何 Asserts.AreEqual 的注释,我会收到错误消息(如下注释)。

保存的实体是:

{
"_id" : "1",
"StringTest" : "Test",
"DateTest" : ISODate("2013-10-12T22:00:00Z")
 }

我知道这可能与 ISODate 和 UTC(我在 UTC+1)有关,但我有点恼火的是我的日期在集合中保存了一天的差异,并且要求我在任何时候获取一些数据时转换为 localTime与日期。

这种行为的原因是什么,有没有办法避免它?

4

2 回答 2

9

在大多数情况下,您希望将 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 值并以它们仍然匹配的方式取回它们,那么您需要在存储它们之前将它们四舍五入到最接近的毫秒。

如果您确实想存储本地时间,我建议您从DateTimeto切换DateTimeOffset并将其序列化为 UTC DateTime 的长 Tick 值和偏移值。

请注意,除非您存储在获取 DateTime 值时计算的偏移量,否则转换为 LocalTime 的 .NET 方法基本上是无用的,因为它们不知道夏令时何时开始,甚至也不知道 DateTime 值来自哪个区域从。总的来说,.NET DateTime 处理还有很多不足之处,并且包含许多声称有帮助但实际上没有帮助的误导性方法。

于 2013-10-13T21:31:39.873 回答
3

您也可以在模型中执行此操作。公共类TestEntity

{
    public string Id { get; set; }

    public string StringTest { get; set; }

    [BsonDateTimeOptions(Kind = DateTimeKind.Utc)]
    public DateTime DateTest { get; set; }
}
于 2019-01-27T03:39:30.333 回答