2015-05-22 2 views
6

Я работаю с базой данных MongoDB. Я знаю, когда вы вставляете DateTime в Mongo, он преобразует его в UTC. Но я делаю единичный тест, и мой Assert не работает.DateTime ToLocalTime сбой

[TestMethod] 
public void MongoDateConversion() { 
    DateTime beforeInsert = DateTime.Now; 
    DateTime afterInsert; 

    Car entity = new Car { 
     Name = "Putt putt", 
     LastTimestamp = beforeInsert 
    }; 

    // insert 'entity' 
    // update 'entity' from the database 

    afterInsert = entity.LastTimestamp.ToLocalTime(); 

    Assert.AreEqual(beforeInsert, afterInsert); // fails here 
} 

У меня должно быть что-то недостающее. Когда я смотрю в отладчике, я могу видеть, что матч в DATETIME в, но по-прежнему утверждают, говорит, что они не делают (но они делают):

Result Message: Assert.AreEqual failed. Expected:<5/21/2015 8:27:04 PM>. Actual:<5/21/2015 8:27:04 PM>. 

Любые идеи, что я делаю неправильно здесь?

EDIT:

Я придумал два возможных решения, оба из которых требуют, чтобы я помню, что-то делать (что не всегда лучше всего полагаться на ...):

Одним из них является использование метода расширения для усечения любой DateTime, выходящей из базы данных:

public static DateTime Truncate(this DateTime dateTime) { 
    var timeSpan = TimeSpan.FromMilliseconds(1); 
    var ticks = -(dateTime.Ticks % timeSpan.Ticks); 
    return dateTime.AddTicks(ticks); 
} 

другого, после прочтения http://alexmg.com/datetime-precision-with-mongodb-and-the-c-driver/, чтобы пометить любой DateTime в классе POCO:

public class Car : IEntity { 
    public Guid Id { get; set; } 

    [BsonDateTimeOptions(Representation = BsonType.Document)] 
    public DateTime LastTimestamp { get; set; } 
} 
+0

Смотрите эту статью, объясняющую MongoDB DATETIME точность: HTTP: // alexmg.com/datetime-precision-with-mongodb-and-the-c-driver/ –

ответ

1

MongoDB хранит DateTimes как 64-разрядное число миллисекунд с эпохи UNIX. См. Эту страницу: http://alexmg.com/datetime-precision-with-mongodb-and-the-c-driver/

Поскольку разрешение DateTime .NET составляет 100 наносекунд, MongoDB почти наверняка усекает любое время DateTime, когда вы в оба конца, как это.

У вас есть несколько вариантов.

Вариант 1: Убедитесь, что вы усечь LastTimestamp, когда вы установите его, или, прежде чем вставить запись:

long excessTicks = timestamp.Ticks % 10000; 

timestamp= new DateTime(
    ticks: timestamp.Ticks - excessTicks, 
    kind: timestamp.Kind 
); 

Этот подход собирается быть подвержен ошибкам. Любой, кто устанавливает LastTimestamp, должен помнить об усечении, или вы можете усечь значение прямо перед вставкой записи, но вам может потребоваться неожиданно изменить объект CLR.

В качестве альтернативы вы можете использовать геттер/сеттер и просто обрезать LastTimestamp до миллисекунд каждый раз, когда он установлен. Но это может привести к тому, что какой-либо другой блок-тест продолжит линию, не соответствующую той же причине, что и этот тест.

Вариант 2: Если точность доли миллисекунды не важно, просто положить некоторую терпимость в ваше утверждение:

TimeSpan delta = beforeInsert - afterInsert; 

Assert.IsTrue(Math.Abs(delta.TotalMilliseconds) <= 2); 
+0

Вместо 'Math.Abs' вы также можете использовать' Assert.IsTrue (delta.Duration(). TotalMilliseconds <= 2); '[Duration()'] (https://msdn.microsoft.com/ru -us/library/system.timespan.duration (v = vs.110) .aspx) возвращает абсолютное значение времени. –

1

Я предполагаю, что у вас есть разница в миллисекундах. Попробуйте усечения миллисекунду, как следующее:

DateTime d = DateTime.Now; 
d = d.AddMilliseconds(-d.Millisecond); 
+0

Это не сработает. DateTime.Millisecond - целое число. Это дает вам только миллисекунду часть значения DateTime. Он всегда находится в диапазоне от 0 до 999, в [записи MSDN] (https://msdn.microsoft.com/en-us/library/system.datetime.millisecond.aspx). – Daryl

1

Ваш тест является неправильным (или непоследовательно), потому что всегда будет разница несколько миллисекунд до и после вставки. Вы могли бы просто преобразовать дату и время в строку, форматированную как dd/mm/yy hh:mm:ss, и сравнить до и после

Смежные вопросы