2015-05-22 25 views
6

Tôi đang làm việc với cơ sở dữ liệu MongoDB. Tôi biết khi bạn chèn một DateTime vào Mongo, nó chuyển đổi nó thành UTC. Nhưng tôi đang làm một bài kiểm tra đơn vị, và Assert của tôi không thành công.Ngày giờ ToLocalTime không

[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 
} 

Tôi phải thiếu điều gì đó hiển nhiên. Khi tôi nhìn vào trình gỡ lỗi, tôi có thể thấy rằng trận đấu của datetime, nhưng khẳng định vẫn nói họ không (nhưng họ làm):

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

Bất kỳ ý tưởng những gì tôi đang làm sai ở đây?

EDIT:

tôi đã đi lên với hai giải pháp khả thi, cả hai đều yêu cầu tôi phải nhớ để làm một cái gì đó (mà không phải lúc nào cũng là điều tốt nhất để dựa vào ...):

một là sử dụng một phương pháp mở rộng để cắt bất kỳ DateTime ra khỏi cơ sở dữ liệu:

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

các khác, sau khi đọc http://alexmg.com/datetime-precision-with-mongodb-and-the-c-driver/, là để gắn thẻ bất kỳ DateTime trong lớp POCO:

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

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

Xem bài viết này giải thích MongoDB datetime chính xác: http: // alexmg.com/datetime-precision-với-mongodb-and-the-c-driver/ –

Trả lời

1

MongoDB lưu trữ DateTimes dưới dạng bit 64 bit của mili giây từ kỷ nguyên UNIX. Xem trang này: http://alexmg.com/datetime-precision-with-mongodb-and-the-c-driver/

Do độ phân giải của DateTime của .NET là 100 nano giây, MongoDB gần như chắc chắn sẽ cắt bớt bất kỳ thời gian DateTime nào mà bạn làm tròn như thế này.

Bạn có một vài tùy chọn.

Lựa chọn 1: Hãy chắc chắn rằng bạn cắt LastTimestamp khi bạn cài đặt nó, hoặc trước khi bạn chèn các bản ghi:

long excessTicks = timestamp.Ticks % 10000; 

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

Cách tiếp cận này sẽ là dễ bị lỗi. Bất cứ ai đặt LastTimestamp sẽ phải nhớ để cắt bớt nó, hoặc bạn có thể cắt bớt giá trị ngay trước khi chèn bản ghi, nhưng bạn có thể cần phải thay đổi đối tượng CLR bất ngờ.

Cách khác, bạn có thể sử dụng trình khởi động/thiết lập và chỉ cắt ngắn LastTimestamp thành mili giây mỗi lần được đặt. Nhưng điều đó có thể dẫn đến một số kiểm tra đơn vị khác tiếp tục lên dòng thất bại cho cùng một lý do chính xác thử nghiệm này là không.

Phương án 2: Nếu độ chính xác phụ millisecond là không quan trọng, chỉ cần đặt một số dung sai vào khẳng định của bạn:

TimeSpan delta = beforeInsert - afterInsert; 

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

Thay vì 'Math.Abs' bạn cũng có thể sử dụng' Assert.IsTrue (delta.Duration(). TotalMilliseconds <= 2); 'The [' Duration() '] (https://msdn.microsoft.com/vi Hàm -us/library/system.timespan.duration (v = vs.110) .aspx) trả về giá trị tuyệt đối của timepan. –

1

Tôi đoán bạn có sự khác biệt trong mili giây. Hãy thử cắt ngắn mili giây như sau:

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

Điều này sẽ không hoạt động. DateTime.Millisecond là số nguyên. Nó cung cấp cho bạn phần mili giây của giá trị DateTime. Nó luôn nằm trong khoảng từ 0 đến 999, theo [mục MSDN] (https://msdn.microsoft.com/en-us/library/system.datetime.millisecond.aspx). – Daryl

1

Thử nghiệm của bạn sai (hoặc không nhất quán) vì sẽ luôn có một vài phần nghìn giây trước và sau khi chèn. Bạn chỉ có thể chuyển đổi datetime thành một chuỗi được định dạng là dd/mm/yy hh:mm:ss và so sánh trước và sau