2013-10-13 14 views
5

Mam następujący test, który przechodzi:MongoDB C# kierowca i 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()); 
     } 
    } 
} 

Gdybym odkomentowaniu któregokolwiek z Asserts.AreEqual pojawia się błąd (skomentowany poniżej).

Zapisana jednostka:

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

Rozumiem, że może to być coś związane z ISODate a UTC (jestem w UTC + 1), ale nieco zirytowany, że moi daty są zapisywane z jedną różnicą dzień w kolekcji i wymaga ode mnie przekonwertowania na localTime w dowolnym momencie, gdy pobierasz dane z datami.

Jaki jest powód takiego zachowania i czy istnieje sposób, aby tego uniknąć?

Odpowiedz

8

W większości przypadków chcesz zapisać UTC date razy w bazie więc DateTime powinien być skonstruowany jako: -

DateTest = new DateTime(2013, 10, 13, 0, 0, 0, DateTimeKind.Utc) //this is the date 

Z tym pierwszym swoim skomentował testów jednostkowych przechodzi teraz.

Bez podania numeru DateTimeKind pozostawiasz przypadek. Wydaje się, że MongoDB zakłada, że ​​jest lokalny i konwertuje go do UTC w bazie danych.

Należy również pamiętać, że wartości MongoDB DateTime mają mniejszą dokładność niż wartości .NET DateTime. Jeśli chcesz przechowywać dowolne wartości DateTime i przywracać je w taki sposób, aby były zgodne, musisz je zaokrąglić do najbliższej milisekundy przed ich zapisaniem.

Jeśli naprawdę chcesz przechowywać czas lokalny, polecam przełączyć z DateTime na DateTimeOffset i serializować go jako długą wartość Tick dla czasu UTC DateTime i wartość dla offsetu.

Należy zauważyć, że dopóki nie zostanie zapisane przesunięcie obliczone w momencie uzyskania wartości DateTime, metody .NET do konwersji na LocalTime są w zasadzie bezużyteczne, ponieważ nie wiedzą, kiedy rozpoczął się czas letni, ani nawet nie wiedzą, która strefa wartość DataTime pochodzi z. Ogólnie rzecz biorąc, obsługa .NET DateTime pozostawia wiele do życzenia i zawiera wiele mylących metod, które twierdzą, że pomagają, ale tak naprawdę nie.

+0

Dzięki! Większy problem został rozwiązany. Próbowałem kod, a także, jeśli pierwsza i druga asercja nadal nie przechodzą na różnicę czasu 2 godziny co najmniej dostaję tego samego dnia ... Rozumiem .Net komplikuje obsługę DateTime, ale w tym przypadku wydaje się, że mi bardziej problem ze sterownikami Mongodb. Dla podstawowych operacji CRUD oczekiwałbym dostać to, co wstawiłem, jak w każdym innym rozwiązaniu. W tym przypadku chcę tylko daty przechowywania (brak czasu) przechowywania tak długo, jak długo komplikuje wyszukiwanie kolekcji bezpośrednio w powłoce mogodb. – Ronnie

Powiązane problemy