2013-05-01 32 views
9

Chúng tôi gặp sự cố khi một nhà phát triển tạo mã bên dưới và hoạt động trên môi trường DEV của anh ấy. Nhưng khi nó được kiểm tra vào QA, mã phá vỡ với thông báo lỗi dưới đây:TimeZoneInfo.ConvertTimeToUtc issue

myRecord.UTCStartTime = TimeZoneInfo.ConvertTimeToUtc(myRecord.StartTime, myTimeZone); 

Việc chuyển đổi không thể hoàn tất vì đã cung cấp DateTime không có tài sản Kind đặt đúng. Ví dụ: khi thuộc tính Loại là DateTimeKind.Local, múi giờ nguồn phải là TimeZoneInfo.Local.

Trên môi trường DEV của tôi, mã ở trên tạo ra lỗi giống như máy chủ QA. Tôi đã áp dụng thay đổi bên dưới để khắc phục sự cố:

DateTime utcStart = DateTime.SpecifyKind(myRecord.StartTime, DateTimeKind.Unspecified); 
myRecord.UTCStartTime = TimeZoneInfo.ConvertTimeToUtc(utcStart, myTimeZone); 

Tại sao ví dụ mã đầu tiên hoạt động trên môi trường DEV1 nhưng phá vỡ môi trường DEV và trên máy chủ QA của chúng tôi?

Trả lời

30

Nó phụ thuộc vào cách myRecord.StartTime được bắt nguồn.

  • Nếu bạn nhận từ DateTime.Now, thì nó sẽ có loại Local.
  • Nếu bạn nhận nó từ DateTime.UtcNow thì nó sẽ có loại Utc.
  • Nếu bạn nhận được từ new DateTime(2013,5,1) thì nó sẽ có loại Unspecified.

Nó cũng phụ thuộc vào nơi bạn nhận được myTimeZone từ. Ví dụ:

  • TimeZoneInfo.Local
  • TimeZoneInfo.Utc
  • TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time")

Chức năng TimeZoneInfo.ConvertTimeToUtc sẽ chỉ hoạt động nếu nó có thể phù hợp với khu vực để các loại bạn cho nó. Nếu cả hai đều là cục bộ, hoặc cả hai đều là UTC, thì nó sẽ hoạt động. Nếu bạn đang cho nó một khu vực cụ thể, thì loại đó sẽ không được chỉ định. Hành vi này là documented on MSDN.

Bạn có thể dễ dàng tái tạo các ngoại lệ nhất quán:

var tz = TimeZoneInfo.FindSystemTimeZoneById("Fiji Standard Time"); 
var utc = TimeZoneInfo.ConvertTimeToUtc(DateTime.Now, tz); 

Giả sử bạn không sống ở Fiji, điều này sẽ báo lỗi mỗi lần. Về cơ bản, bạn nói, "chuyển đổi thời gian địa phương của tôi, ở một số khu vực khác, để utc" - mà không có ý nghĩa.

Nó có thể hoạt động trong môi trường dev của bạn bởi vì giá trị bạn đang thử nghiệm cho myTimeZone xảy ra là khu vực địa phương cho nhà phát triển.

Về thay đổi của bạn - chắc chắn bạn có thể buộc loại đó không được chỉ định và điều đó thay đổi ý nghĩa của những gì bạn đang làm để có ý nghĩa. Nhưng bạn có chắc chắn đây là những gì bạn muốn? .Kind của ngày trước khi bàn tay là gì? Nếu nó không phải là Unspecified, thì nó đang mang một số ý định. Bạn có lẽ nên quay trở lại nguồn của dữ liệu này và chắc chắn rằng đó là những gì bạn mong đợi.

Nếu tất cả những điều này nghe có vẻ điên rồ, điên rồ, bực mình và kỳ quái, đó là vì đối tượng địa lý bị chặn DateTime. Dưới đây là một số bài đọc thêm:

Bạn có thể xem xét sử dụng NodaTime để thay thế. API của nó sẽ ngăn bạn tạo ra những loại lỗi phổ biến này.

1

trong ví dụ này tôi đã chuyển đổi múi giờ địa phương để loại không xác định vì vậy nó được làm việc tốt cho tôi bằng cách sử dụng "DateTime.SpecifyKind()" phương pháp

DateTime.SpecifyKind (utc, DateTimeKind.Unspecified);

phương pháp này Tạo đối tượng DateTime mới có cùng số lượng tick như DateTime đã chỉ định, nhưng được chỉ định là loại DateTimeKind không xác định.

public static DateTime ConvertLocalDate (DateTime utc) {

 string id = ConfigurationManager.AppSettings["Timezone"].ToString(); 
     TimeZoneInfo cstZone = TimeZoneInfo.FindSystemTimeZoneById(id); 
     utc = DateTime.SpecifyKind(utc,DateTimeKind.Unspecified); 
     DateTime cstTime = TimeZoneInfo.ConvertTimeFromUtc(utc, cstZone); 
     return cstTime; 
    } 
1

Tôi tìm thấy một giải pháp thực sự đơn giản ở đây https://kiranpatils.wordpress.com/2011/01/09/the-conversion-could-not-be-completed-because-the-supplied-datetime-did-not-have-the-kind-property-set-correctly-for-example-when-the-kind-property-is-datetimekind-local-the-source-time-zone-must/

nào chỉ xuất hiện để thể xảy ra khi bạn sử dụng DateTime.Now . Tôi cập nhật mã của tôi như sau và nó đang hoạt động trở lại :)

DateTime currentTime = new DateTime (DateTime.Now.Ticks, DateTimeKind.Unspecified);

1

sử dụng Datetime.SpecifyKind:

var localDateTime = DateTime.SpecifyKind(localDate, DateTimeKind.Unspecified); 

var utcDateTime = TimeZoneInfo.ConvertTimeToUtc(localDateTime, timeZoneId); 
+0

Bạn chưa trả lời câu hỏi - "Tại sao các mã đầu tiên ví dụ làm việc trên môi trường DEV1 nhưng phá vỡ trên môi trường DEV của tôi và trên máy chủ của chúng tôi bảo đảm chất lượng?" – Enigmativity

+0

Mã này giống như cách giải quyết được đề cập trong câu hỏi. – BACON