2015-02-19 37 views
5
DateTime d1=new DateTime(2015, 1, 1, 0, 0, 0, DateTimeKind.Utc); 
DateTime d2=new DateTime(2015, 1, 1, 0, 0, 0, DateTimeKind.Local); 
Console.WriteLine(d1==d2);   // prints true 
Console.WriteLine(d1<d2);   // prints false 
Console.WriteLine(d1.CompareTo(d2)); // prints 0 
Console.WriteLine(d1.ToUniversalTime()==d2.ToUniversalTime()); // prints false 

Điều này giống như một lỗi đối với tôi, nếu không phải là color me surprised.DateTime So sánh Bỏ qua Loại?

Tôi có phải gọi ToUniversalTime() cho mỗi lần so sánh hoặc có phương án thay thế tốt hơn không?

Làm cách nào để tránh các cạm bẫy như quên gọi ToUniversalTime() hoặc nhận kết quả sai do DateTimeKind.Unspecified?

+0

Không * chính xác *, trong tài liệu - bạn phải đảm bảo thời gian ở cùng múi giờ. Bên cạnh đó, 'DateTime' không bao gồm bất kỳ thông tin múi giờ nào. Bạn cần 'DateTimeOffset' cho tài liệu –

+1

này nêu rõ điều này * Trước khi so sánh các đối tượng DateTime, hãy đảm bảo rằng các đối tượng đại diện cho thời gian trong cùng một múi giờ. Bạn có thể làm điều này bằng cách so sánh các giá trị thuộc tính Kind của chúng. * –

+1

'NodaTime' để giải cứu :) – tchrikch

Trả lời

5

Tài liệu MSDN khá rõ ràng rằng DateTimeKind không được tính đến bằng toán tử Bình đẳng.

Toán tử bình đẳng xác định xem hai giá trị DateTime có bằng nhau hay không bằng cách so sánh số lượng bọ ve của chúng. Trước khi so sánh đối tượng DateTime, hãy đảm bảo rằng các đối tượng đại diện cho thời gian trong cùng một múi giờ. Bạn có thể làm điều này bằng cách so sánh các giá trị thuộc tính Kind của chúng.

MSDN - DateTime.Equality Operator

Bạn có thể viết phương pháp khuyến nông của riêng bạn để bao gồm các DateTimeKind so sánh:

public static bool EqualsWithKind(this DateTime time, DateTime other) 
{ 
     return time.Kind == other.Kind && 
      time == other; 
} 

Có tính đến ý kiến ​​từ Panagiotis KanavosJames Thorpe về DateTimeOffset:

Sử dụng nếu bù được đảm bảo giống như bù đắp cục bộ.

public static bool EqualsWithTimezone(this DateTime time, DateTime other) 
{ 
     return new DateTimeOffset(time) == new DateTimeOffset(other); 
} 

Sử dụng nếu offsets KHÔNG đảm bảo để được như vậy:

public static bool EqualsInclTimezone(this DateTime time, TimeSpan timeOffset, DateTime other, TimeSpan otherOffset) 
{ 
     return new DateTimeOffset(time, timeOffset) == new DateTimeOffset(other, otherOffset); 
} 
+0

Bạn đánh bại tôi với nó +1 –

+0

Bạn có thể cho tôi một giải pháp thay thế tránh được sự cố này không? – laktak

+0

Không sử dụng DateTime, sử dụng DateTimeOffset bao gồm bù đắp tz. Tốt hơn, hãy sử dụng Thời gian Noda sử dụng tên múi giờ thực tế và điều chỉnh bù đắp để tiết kiệm ánh sáng ban ngày. Không thể thiếu cho tính toán du lịch hàng không –

-1

Trông đúng với tôi.

1/1/2015 15:00:00 (UTC) (cũng GMT - Bằng giờ Greenwich Mean Time)

1/1/2015 15:00:00 (địa phương - cho phép nói theo giờ địa phương là ở NYC)

hai lần và ngày này bằng so sánh.

Nhưng chuyển đổi thứ hai để UTC và nó sẽ bỏ qua 5 giờ để trở thành UTC/GMT

1/1/2015 20:00:00 - và họ không còn bình đẳng!

0

Đó không phải là lỗi chính xác nhưng thiếu sót là DateTime. Loại DateTime không hỗ trợ thông tin múi giờ ngoài chỉ báo cục bộ/UTC. Nó nói như vậy trong các tài liệu - bạn phải đảm bảo ngày tháng trong cùng một múi giờ - không chỉ có cùng một loại. DateTimeKind.Local không nói gì về múi giờ thực sự được sử dụng.

Nếu bạn quan tâm đến múi giờ, bạn nên luôn sử dụng loại DateTimeOffset.Nó được giới thiệu trong .NET 3.5 một phần để giải quyết các múi giờ. DateTimeOffset tương đương với loại datetimeoffset của Máy chủ SQL và chứa chênh lệch múi giờ cùng với thời gian, cho phép so sánh và chuyển đổi giữa múi giờ bù trừ. Điều này cũng cho phép bạn lưu trữ và sử dụng thông tin thời gian hoàn chỉnh trong mã và cơ sở dữ liệu, tránh các lỗi chuyển đổi.

Điều này tương tự như việc sử dụng nvarchar thay vì varchar để tránh lỗi chuyển đổi mã.

Múi giờ có thể có các chênh lệch khác nhau mặc dù do tiết kiệm ban ngày. Quy tắc tiết kiệm ánh sáng ban ngày cũng thay đổi - luật lệ của Nga đã thay đổi ít nhất 4 lần trong 10 năm qua. Windows và .NET không có bản sửa lỗi cho điều này.

Đây có thể là sự cố, ví dụ như trong ngành du lịch. Trong những trường hợp như vậy, bạn có thể sử dụng thư viện như Noda Time, chứa cơ sở dữ liệu múi giờ IANA với tất cả các quy tắc múi giờ đã biết.

Các vấn đề liên quan