2013-10-13 8 views
5

私が通過する次のテストがありますMongoDBのC#のドライバとISODate

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") 
} 

が、私はこれが何か私の日付が1日違いで保存されていることを少しイライラISODateとUTC(私はUTC + 1にしています)が、私に関連する可能性があることを理解します私は日付を持つデータを取得するたびにlocalTimeに変換する必要があります。

この動作の理由は何ですか?回避する方法はありますか?

答えて

8

は、ほとんどのケースで、あなたの日時は次のように構築されなければならないので、データベースにUTCの日付時刻を格納したい: - これはあなたのコメントのユニットテストの最初で

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 DateTimeの長いTick値とオフセットの値としてシリアル化してください。

DateTime値が取得された時点で計算されたオフセットを保存しない限り、LocalTimeに変換する.NETメソッドは、夏時間の開始時期を知らないため、また、どのゾーンDateTime値はからです。全体として、.NET DateTimeの処理には多くの課題が残されていますが、実際には役立たないと主張する多くの誤解を招く方法が含まれています。

+0

ありがとうございました!より大きな問題は解決されます。 コードを試しましたが、最初と2番目のアサーションがまだ2時間の時間差を渡していないのであれば、少なくとも私は同じ日になります... .NetはDateTime処理を複雑にしますが、私はもっ​​とMongodbのドライバの問題です。 基本的なCRUD操作については、私が他のソリューションと同様に挿入したものを得ることが期待されます。 この場合、mogodbシェルにコレクションを直接照会するのがずっと複雑なので、ティックを格納している日付(時間なし)のみを格納します。 – Ronnie

関連する問題