Bạn đang thiếu một điểm quan trọng: A DateTime
loại nào là Local
không phải lúc nào cũng đại diện cho một khoảnh khắc độc đáo kịp thời. Đó là lý do tại sao không có ánh xạ trực tiếp tới một số Instant
.
Trong quá trình chuyển đổi DST bị thu gọn, một địa phương DateTime
có thể là một trong hai khoảnh khắc có thể có trong thời gian. Nếu bạn định chuyển đổi nó thành một số Instant
, thì ở đâu đó bạn cần quyết định thời điểm nào bạn nên chọn.
Trong câu trả lời bạn đã cho, tôi giả sử bạn có được timezone
từ một trong các cách sau:
var timezone = DateTimeZoneProviders.Tzdb.GetSystemDefault();
hoặc
var timezone = DateTimeZoneProviders.Bcl.GetSystemDefault();
Hoặc là ok cho nhiệm vụ này. Sau đó, các mã bạn đã cho:
var localTime = LocalDateTime.FromDateTime(time);
var zonedTime = localTime.InZoneStrictly(timeZone);
return zonedTime.ToInstant();
Đây chính là chính xác, nhưng kể từ khi bạn sử dụng InZoneStrictly
, bạn sẽ nhận được một AmbiguousTimeException
trong quá trình chuyển mùa thu trở lại.
Bạn có thể tránh điều này bằng cách sử dụng InZoneLeniently
, thao tác này sẽ chọn sau hai khả năng (thường là thời gian "Chuẩn"). Nhưng quan trọng hơn, thay vào đó, bạn có thể sử dụng InZone
và cung cấp resolver tiêu chuẩn hoặc tùy chỉnh để kiểm soát hành vi chính xác hơn.
Về cách tiếp cận ban đầu của bạn về:
Instant.FromDateTimeUtc(time.ToUniversalTime())
Đây là ok và sẽ không bị hỏng dữ liệu của bạn, nhưng hiểu rằng nó sẽ dựa vào hành vi của BCL của địa phương để chuyển đổi phổ quát. Nó giống hệt với InZoneLeniently
, trong đó một giá trị mơ hồ sẽ được coi là thời gian "chuẩn".
Đây là ví dụ tuyệt vời về cách NodaTime cung cấp API chính xác hơn. Thay vì đưa ra các giả định, bạn có cơ hội để cụ thể và cung cấp hành vi tùy chỉnh. Cuối cùng, bạn đã đạt được kết quả tương tự, nhưng nó đưa vấn đề này lên nền trước thay vì ẩn nó.
Cảm ơn bạn đã dành thời gian giải thích điều này. Tôi nghĩ điều này sẽ hữu ích cho những người mới đến thư viện. – Sam