2008-10-07 14 views
244

Chúng tôi đang phát triển một ứng dụng C# cho một khách hàng dịch vụ web. Điều này sẽ chạy trên Windows XP PC.Chuyển đổi giờ UTC/GMT thành giờ địa phương

Một trong các trường được dịch vụ web trả về là trường DateTime. Máy chủ trả về một trường theo định dạng GMT, tức là có dấu "Z" ở cuối.

Tuy nhiên, chúng tôi thấy rằng .NET dường như thực hiện một số loại chuyển đổi tiềm ẩn và thời gian luôn là 12 giờ.

Mẫu mã sau đây giải quyết vấn đề này ở một mức độ nào đó mà sự khác biệt 12 giờ đã biến mất nhưng nó không cho phép tiết kiệm ánh sáng ban ngày của NZ.

CultureInfo ci = new CultureInfo("en-NZ"); 
string date = "Web service date".ToString("R", ci); 
DateTime convertedDate = DateTime.Parse(date);    

Theo this date site:

UTC/GMT offset

múi giờ chuẩn: UTC/GMT 12 giờ
điều chỉnh giờ: +1 giờ khu
Thời gian hiện tại bù đắp : UTC/GMT +13 giờ

Làm cách nào để điều chỉnh thêm giờ? Điều này có thể được thực hiện theo chương trình hoặc là một số loại thiết lập trên PC?

+1

'cái thời gian Z' đề cập đến UTC, không giờ GMT. Cả hai có thể khác nhau lên đến 0,9 giây. – mc0e

Trả lời

42
TimeZone.CurrentTimeZone.ToLocalTime(date); 
+8

Điều này chỉ hoạt động nếu hệ thống biết rằng ngày đang được chuyển đổi từ UTC. Xin vui lòng xem câu trả lời của tôi. –

+1

Nhưng UTC là mặc định phải không? Do đó nó hoạt động cho "không xác định" như trong câu trả lời của CJ7. – NickG

2

Trong câu trả lời cho đề nghị của Dana:

Các mẫu mã bây giờ trông giống như:

string date = "Web service date"..ToString("R", ci); 
DateTime convertedDate = DateTime.Parse(date);    
DateTime dt = TimeZone.CurrentTimeZone.ToLocalTime(convertedDate); 

Ngày ban đầu là 20/08/08; loại này là UTC.

Cả hai "conversionDate" và "dt" đều giống nhau:

21/08/08 10:00:26; loại này là địa phương

+0

Xin vui lòng xem câu trả lời của tôi cho một lời giải thích về điều này. –

1

Tôi gặp sự cố với tập dữ liệu đang được đẩy qua dây (dịch vụ web đến ứng dụng khách) sẽ tự động thay đổi vì trường DateType của DataColumn được đặt thành cục bộ. Đảm bảo bạn kiểm tra xem DateType là gì nếu bạn đẩy DataSets qua.

Nếu bạn không muốn thay đổi, hãy đặt thành Không xác định

13

Tôi chỉ muốn thêm lưu ý chung về thận trọng.

Nếu tất cả những gì bạn đang làm là lấy thời gian hiện tại từ đồng hồ bên trong của máy tính để đặt ngày/giờ trên màn hình hoặc báo cáo, thì tất cả đều tốt. Nhưng nếu bạn đang lưu thông tin ngày/giờ để tham khảo sau này hoặc là tính toán ngày/giờ, hãy cẩn thận!

Giả sử bạn xác định rằng tàu du lịch đến Honolulu vào ngày 20 tháng 12 năm 2007 lúc 15:00 UTC. Và bạn muốn biết giờ địa phương là gì.
1. Có thể có ít nhất ba 'người dân địa phương' tham gia. Địa phương có thể có nghĩa là Honolulu, hoặc nó có thể có nghĩa là nơi máy tính của bạn được đặt, hoặc nó có thể có nghĩa là vị trí mà khách hàng của bạn nằm.
2. Nếu bạn sử dụng các hàm tích hợp để thực hiện chuyển đổi, có thể nó sẽ sai. Điều này là do thời gian tiết kiệm ánh sáng ban ngày (có thể) hiện đang có hiệu lực trên máy tính của bạn, nhưng KHÔNG có hiệu lực vào tháng 12. Nhưng Windows không biết điều này ... tất cả nó có là một lá cờ để xác định nếu thời gian tiết kiệm ánh sáng ban ngày hiện đang có hiệu lực. Và nếu nó hiện đang có hiệu lực, sau đó nó sẽ hạnh phúc thêm một giờ thậm chí cho một ngày trong tháng mười hai.
3. Thời gian tiết kiệm ánh sáng ban ngày được thực hiện khác nhau (hoặc không hề) trong các phân mục chính trị khác nhau. Đừng nghĩ rằng chỉ vì đất nước của bạn thay đổi vào một ngày cụ thể, các quốc gia khác cũng vậy.

+5

Thực tế, # 2 không hoàn toàn chính xác. Có các quy tắc thực tế về DST trong mọi múi giờ mà máy tính của bạn sẽ biết nếu thông tin đã được cài đặt (và cập nhật). Đối với nhiều vùng, các quy tắc đó được sửa. Những người khác thực hiện "DST động". Brazil là peeve thú cưng của tôi cho việc này. Tóm lại, mặc dù máy tính tiền của bạn có thể hoạt động nếu giờ địa phương của bạn sẽ là DST vào tháng 12, giả sử rằng không có thay đổi nào được chuyển thành luật từ bây giờ. –

+0

Thậm chí nếu bạn không sống ở Brazil, DST là "năng động" trong các chính trị gia có thể thay đổi nó bất cứ lúc nào (như đã được thực hiện một vài năm trước đây ở Hoa Kỳ). Vì phần lớn phần mềm được viết với mục đích sử dụng trong tương lai, điều quan trọng là phải nhận ra rằng KHÔNG có cách thức thực tế, có thể đoán trước hoặc thậm chí lý thuyết để biết các quy tắc DST nào sẽ có hiệu lực. Bạn có thể nhận được gần gũi, nhưng tiết kiệm cho mình một số thất vọng bằng cách từ bỏ sự hoàn hảo. – DaveWalley

4

Đừng quên nếu bạn đã có một đối tượng DateTime và không chắc chắn nếu nó UTC hoặc địa phương, nó đủ dễ dàng để sử dụng các phương pháp trên đối tượng trực tiếp:

DateTime convertedDate = DateTime.Parse(date); 
DateTime localDate = convertedDate.ToLocalTime(); 

Làm thế nào để chúng tôi điều chỉnh cho thêm giờ?

Trừ khi được chỉ định .net sẽ sử dụng cài đặt máy tính cục bộ. Tôi muốn có một chi của: http://msdn.microsoft.com/en-us/library/system.globalization.daylighttime.aspx

Bởi vẻ mã có thể giống như thế:

DaylightTime daylight = TimeZone.CurrentTimeZone.GetDaylightChanges(year); 

Và như đã đề cập ở trên kiểm tra lại những gì múi giờ thiết lập máy chủ của bạn là về. Có những bài viết trên mạng để biết làm thế nào để an toàn ảnh hưởng đến những thay đổi trong IIS.

+0

Hệ thống sẽ xử lý sự hài hước này cho bạn, miễn là bạn nói cho hệ thống biết loại 'ngày' của bạn là gì (địa phương/utc/không xác định). –

103

Tôi muốn xem xét sử dụng lớp System.TimeZoneInfo nếu bạn đang sử dụng .NET 3.5. Xem http://msdn.microsoft.com/en-us/library/system.timezoneinfo.aspx. Điều này sẽ đưa vào tài khoản thay đổi tiết kiệm ánh sáng ban ngày một cách chính xác.

// Coordinated Universal Time string from 
// DateTime.Now.ToUniversalTime().ToString("u"); 
string date = "2009-02-25 16:13:00Z"; 
// Local .NET timeZone. 
DateTime localDateTime = DateTime.Parse(date); 
DateTime utcDateTime = localDateTime.ToUniversalTime(); 

// ID from: 
// "HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Time Zone" 
// See http://msdn.microsoft.com/en-us/library/system.timezoneinfo.id.aspx 
string nzTimeZoneKey = "New Zealand Standard Time"; 
TimeZoneInfo nzTimeZone = TimeZoneInfo.FindSystemTimeZoneById(nzTimeZoneKey); 
DateTime nzDateTime = TimeZoneInfo.ConvertTimeFromUtc(utcDateTime, nzTimeZone); 
+0

Nếu bạn đang làm việc trong múi giờ của riêng bạn (en-NZ trong trường hợp này) thì bạn không cần phải đối phó với TimeZoneInfo. Nó chỉ là sự phức tạp không cần thiết. Xem câu trả lời của tôi để biết thêm chi tiết. –

+32

+1 cho máy chủ không giả định ở New Zealand – ajbeaven

+8

Và nếu có nhu cầu, đây là danh sách múi giờ tôi đã tìm thấy cho TimeZoneInfo.FindSystemTimeZoneById - http://www.codeproject.com/Messages/3867850/Csharp-NET- Danh sách-of-timezones-cho-TimeZoneInfo-Find.aspx – kape123

329

Đối với chuỗi như 2012-09-19 01:27:30.000, DateTime.Parse có thể không biết những gì múi giờ ngày và thời gian là từ.

DateTimeKind bất động sản, trong đó có thể có một trong những lựa chọn khu vực ba thời gian:

  • Unspecified
  • Local
  • Utc

LƯU ÝNếu bạn là muốn đại diện cho một ngày/giờ khác với giờ UTC hoặc giờ địa phương của bạn e vùng, sau đó bạn nên sử dụng DateTimeOffset.


Vì vậy, đối mã trong câu hỏi của bạn:

DateTime convertedDate = DateTime.Parse(dateStr); 

var kind = convertedDate.Kind; // will equal DateTimeKind.Unspecified 

Bạn nói rằng bạn biết nó là gì loại, vì vậy nói với nó.

DateTime convertedDate = DateTime.SpecifyKind(
    DateTime.Parse(dateStr), 
    DateTimeKind.Utc); 

var kind = convertedDate.Kind; // will equal DateTimeKind.Utc 

Bây giờ, khi hệ thống biết nó ở UTC thời gian, bạn có thể chỉ cần gọi ToLocalTime:

DateTime dt = convertedDate.ToLocalTime(); 

này sẽ cung cấp cho bạn những kết quả mà bạn yêu cầu.

+17

chỉ là một cách khác để xác định loại: 'DateTime conversionTime = new DateTime (DateTime.Parse (dateStr) .Ticks), DateTimeKind.Utc);' – Brad

+0

phải không ToLocalTime()? @ Brad - parens của bạn không phù hợp. – TrueWill

+0

Cảm ơn @TrueWill. Đã cập nhật. –

1

Tôi đã xem qua câu hỏi này vì tôi gặp sự cố với ngày UTC bạn quay lại thông qua API twitter (trường created_at trên trạng thái); Tôi cần phải chuyển đổi chúng thành DateTime. Không có câu trả lời/mẫu mã nào trong câu trả lời trên trang này đủ để ngăn tôi nhận được lỗi "Chuỗi không được nhận dạng là Ngày giờ hợp lệ" (nhưng đó là gần nhất tôi phải tìm câu trả lời đúng trên SO)

Đăng liên kết này tại đây trong trường hợp điều này giúp người khác - câu trả lời tôi cần được tìm thấy trên bài đăng trên blog này: http://www.wduffy.co.uk/blog/parsing-dates-when-aspnets-datetimeparse-doesnt-work/ - về cơ bản sử dụng DateTime.ParseExact với chuỗi định dạng thay vì DateTime.Parse

15

Tôi biết đây là câu hỏi cũ hơn , nhưng tôi đã rơi vào một tình huống tương tự, và tôi muốn chia sẻ những gì tôi đã tìm thấy cho những người tìm kiếm trong tương lai, có thể bao gồm cả bản thân mình :).

DateTime.Parse() có thể phức tạp - xem ví dụ here.

Nếu DateTime đang đến từ một dịch vụ Web hoặc một số nguồn khác với một định dạng được biết đến, bạn có thể muốn xem xét cái gì đó như

DateTime.ParseExact(dateString, 
        "MM/dd/yyyy HH:mm:ss", 
        CultureInfo.InvariantCulture, 
        DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal) 

hoặc, thậm chí tốt hơn,

DateTime.TryParseExact(...) 

Các AssumeUniversal cờ báo cho trình phân tích cú pháp rằng ngày/giờ đã là UTC; sự kết hợp của AssumeUniversalAdjustToUniversal yêu cầu không chuyển đổi kết quả thành thời gian "cục bộ", theo mặc định nó sẽ cố gắng thực hiện. (Tuy nhiên, cá nhân tôi cố gắng giao dịch độc quyền với UTC trong lớp kinh doanh/ứng dụng/dịch vụ. Nhưng bỏ qua việc chuyển đổi thành giờ địa phương cũng tăng tốc độ lên 50% hoặc hơn trong các thử nghiệm của tôi, xem bên dưới.)

đây là những gì chúng tôi đã làm trước đây:

DateTime.Parse(dateString, new CultureInfo("en-US")) 

chúng tôi đã cấu hình ứng dụng và phát hiện ra rằng DateTime.Parse đại diện cho một tỷ lệ đáng kể của việc sử dụng CPU. (Ngẫu nhiên, các nhà xây dựng CultureInfokhông một đóng góp đáng kể cho việc sử dụng CPU.)

Vì vậy, tôi thiết lập một ứng dụng giao diện điều khiển để phân tích một chuỗi ngày/giờ 10000 lần trong nhiều cách khác nhau. Bottom line:
Parse() 10 giây
ParseExact() (chuyển sang địa phương) 20-45 ms
ParseExact() (không quy đổi để địa phương) 10-15 ms
... và có, các kết quả cho Parse() là trong giây , trong khi những người khác nằm trong mili giây.

+3

+1 Để lập cấu hình các phương thức phân tích cú pháp. Tốt để biết! –

15

DateTime đối tượng có Kind của Unspecified theo mặc định, cho mục đích ToLocalTime được giả định là UTC.

Để có được thời gian địa phương của một đối tượng UnspecifiedDateTime, bạn do đó chỉ cần làm điều này:

convertedDate.ToLocalTime(); 

Các bước thay đổi Kind của DateTimeUnspecified-UTC là không cần thiết.Unspecified được giả định là UTC cho các mục đích của ToLocalTime: http://msdn.microsoft.com/en-us/library/system.datetime.tolocaltime.aspx

+1

Và ngược lại: 'conversionDate.FromLocalTime();' sẽ chuyển thành 'UTC'. –

1
@TimeZoneInfo.ConvertTimeFromUtc(timeUtc, TimeZoneInfo.Local)