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です)が、コレクションに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 値を保存し、それらがまだ一致するような方法でそれらを取得したい場合は、それらを保存する前に最も近いミリ秒に丸める必要があります。

本当に現地時間を保存したい場合は、に切り替えて、UTC DateTime の long Tick 値とオフセットの値としてシリアル化することをお勧めしDateTimeますDateTimeOffset

DateTime 値が取得された時点で計算されたオフセットを格納しない限り、LocalTime に変換する .NET メソッドは、夏時間がいつ開始されたかがわからず、DateTime 値がどのゾーンに来るかさえわからないため、本質的に役に立たないことに注意してください。から。全体として、.NET の DateTime 処理には多くの要望が残されています。また、役立つと主張しているが実際には役に立たない、誤解を招くメソッドが多数含まれています。

于 2013-10-13T21:31:39.873 に答える