2010-06-02 29 views
57

Tôi đang cố gắng sử dụng DateTimeOffset để truyền đạt thời điểm cụ thể theo thời gian trên bất kỳ múi giờ nào. Tôi không thể tìm ra cách sử dụng TimeZoneInfo để xử lý thời gian tiết kiệm ánh sáng ban ngày.Cách sử dụng TimeZoneInfo để nhận giờ địa phương trong Thời gian Tiết kiệm Ánh sáng ban ngày?

var dt = DateTime.UtcNow; 
Console.WriteLine(dt.ToLocalTime()); 

var tz = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time"); 
var utcOffset = new DateTimeOffset(dt, TimeSpan.Zero); 
Console.WriteLine(utcOffset.ToOffset(tz.BaseUtcOffset)); 

này in ra:

6/2/2010 4:37:19 PM 
6/2/2010 3:37:19 PM -06:00 

Tôi đang ở múi giờ miền Trung, và và chúng tôi hiện đang trong thời gian tiết kiệm ánh sáng ban ngày. Tôi đang cố gắng đọc dòng thứ hai:

6/2/2010 4:37:19 PM -05:00 

BaseUtcBộ ngoại tuyến dường như không thay đổi dựa trên DST.

Làm cách nào để có được đúng thời điểm với giá trị offset phù hợp?

+9

+1 - nó làm tôi điên mà TimeZoneInfo.ConvertTimeBySystemTimeZoneId không chỉ làm việc cho :) này –

Trả lời

47

Bạn cần phải nhận được UTCOFFSET từ TimeZoneInfo, sau đó vượt qua đó đến ToOffset() phương pháp:

var dt = DateTime.UtcNow; 
Console.WriteLine(dt.ToLocalTime()); 

var tz = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time"); 
var utcOffset = new DateTimeOffset(dt, TimeSpan.Zero); 
Console.WriteLine(utcOffset.ToOffset(tz.GetUtcOffset(utcOffset))); 
+0

tôi thấy ... bạn đã có để có được tính theo giờ UTC bù đắp cho điều đó ngày cụ thể trong múi giờ. cảm ơn. – jaminto

+3

Đây không phải là cách tốt nhất so với [câu trả lời của Karl Gjertsen] (http://stackoverflow.com/a/16789973/57611) sử dụng một hàm .Net duy nhất để thực hiện công việc thay vì trích xuất bù đắp thông qua tạo mới, vứt bỏ 'DateTimeOffset'. – ErikE

35

Bạn cũng có thể sử dụng TimeZoneInfo.ConvertTimeFromUtc, mà sẽ cho phép tiết kiệm thời gian ban ngày:

DateTime utc = DateTime.UtcNow; 
TimeZoneInfo zone = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time"); 
DateTime localDateTime = TimeZoneInfo.ConvertTimeFromUtc(utc, zone); 
5

Hoặc tốt hơn, nếu bạn không muốn cứng mã nhận dạng khu thời gian:

TimeZoneInfo tzi = TimeZoneInfo.FindSystemTimeZoneById(TimeZoneInfo.Local.Id); 
DateTime localDateTime = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, tzi); 
+0

Bạn không thể sử dụng 'TimeZoneInfo.Local' trực tiếp? Tại sao bạn cần cuộc gọi đến 'FindSystemTimeZoneById'? – CoderDennis

+1

Bạn nói đúng, chúng tôi không cần nó. Chúng ta có thể thực hiện nó như thế này 'DateTime localDateTime = TimeZoneInfo.ConvertTimeFromUtc (networkDateTime, TimeZoneInfo.' – Pabinator

+0

Nhưng sau đó bạn được cố định vào một múi giờ duy nhất. Phụ thuộc vào cách bạn muốn sử dụng mã tôi đoán. :-) –

1

Tôi là người mới bắt đầu cả ở .NET và stackoverflow, vì vậy tôi có thể sai, nhưng ở đây đi:

Sử dụng TimeZoneInfo.ConvertTimeFromUtc sẽ cho phép tiết kiệm ánh sáng ban ngày và chuyển đổi đúng thời gian theo thời gian vùng + chênh lệch DST có thể. Tuy nhiên - bù đắp chính nó trong đối tượng kết quả sẽ hiển thị độ lệch cho thời gian tiêu chuẩn và không tính đến thời gian tiết kiệm ánh sáng ban ngày. Vì vậy, nếu bạn muốn làm một ToString trên đối tượng, bạn sẽ kết thúc với thời gian chính xác (theo giờ và phút), nhưng bù sai trong thời gian tiết kiệm ánh sáng ban ngày, có thể dẫn đến sai thời điểm sau đó trong mã.

Nếu bạn thay vì sử dụng GetUtcOffset để lấy giá trị bù cho một thời gian cụ thể và sau đó thực hiện một ToOffset trên đối tượng DateTimeOffset, cả giờ/phút và bản thân giá trị sẽ được chuyển đổi chính xác và bạn có thể thực hiện lệnh ToString một cách an toàn .

string ExpectedDateTimePattern = "yyyy'-'MM'-'dd'T'HH':'mm':'ss''zzz"; 
string timeZoneId = "FLE Standard Time"; 
string dateTimestr = "2017-10-09T09:00:00+02:00"; 

DateTimeOffset dto = DateTimeOffset.Parse(dateTimeStr); 
TimeZoneInfo zone = TimeZoneInfo.FindSystemTimeZoneById(timeZoneId); 
TimeSpan offset = zone.GetUtcOffset(dto); 
dto = dto.ToOffset(offset); 
string localTime = dto.ToString(ExpectedDateTimePattern); 

localTime sẽ trả về "2017-10-09T10: 00: 00 + 03: 00".

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