Tworzymy aplikację C # dla klienta usługi sieciowej. Będzie działać na komputerach z systemem Windows XP.
Jednym z pól zwracanych przez usługę internetową jest pole DateTime. Serwer zwraca pole w formacie GMT, tj. Z „Z” na końcu.
Odkryliśmy jednak, że .NET wydaje się dokonywać jakiejś niejawnej konwersji, a czas zawsze wynosił 12 godzin.
Poniższy przykładowy kod rozwiązuje to w pewnym stopniu, ponieważ minęła 12 godzinna różnica, ale nie uwzględnia ona czasu letniego w NZ.
CultureInfo ci = new CultureInfo("en-NZ");
string date = "Web service date".ToString("R", ci);
DateTime convertedDate = DateTime.Parse(date);
Zgodnie z tą datą strona :
Przesunięcie UTC / GMT
Standardowa strefa czasowa: UTC / GMT +12 godzin
Czas letni: +1 godzina
Bieżące przesunięcie strefy czasowej: UTC / GMT +13 godzin
Jak dostosowujemy się do dodatkowej godziny? Czy można to zrobić programowo, czy jest to jakieś ustawienie na komputerze?
Z
czas odnosi się do UTC, a nie GMT. Oba mogą się różnić o maksymalnie 0,9 sekundy.Odpowiedzi:
Ciągów, takich jak
2012-09-19 01:27:30.000
,DateTime.Parse
nie może powiedzieć, co strefa czasowa data i czas są od.DateTime
ma właściwość Kind , która może mieć jedną z trzech opcji strefy czasowej:UWAGA Jeśli chcesz podać datę / godzinę inną niż UTC lub lokalną strefę czasową, powinieneś użyć
DateTimeOffset
.Więc dla kodu w twoim pytaniu:
Mówisz, że wiesz, jaki to rodzaj, więc powiedz to.
Teraz, gdy system pozna czas UTC, możesz po prostu zadzwonić
ToLocalTime
:To da ci wynik, którego potrzebujesz.
źródło
DateTime convertedTime = new DateTime(DateTime.Parse(dateStr).Ticks), DateTimeKind.Utc);
Kind
zDateTime
odUnspecified
celuUTC
nie jest konieczne.Unspecified
zakłada się, że jestUTC
do celówToLocalTime
: msdn.microsoft.com/en-us/library/…Chciałbym skorzystać z klasy System.TimeZoneInfo, jeśli jesteś w .NET 3.5. Zobacz http://msdn.microsoft.com/en-us/library/system.timezoneinfo.aspx . Powinno to prawidłowo uwzględniać zmiany czasu letniego.
źródło
źródło
DateTime
obiekty mająKind
zUnspecified
domyślnie, który dla celówToLocalTime
zakłada sięUTC
.Aby uzyskać czas lokalny
Unspecified
DateTime
obiektu, musisz po prostu to zrobić:Etap zmieniając
Kind
zDateTime
odUnspecified
celuUTC
nie jest konieczne.Unspecified
zakłada się, że jestUTC
do celówToLocalTime
: http://msdn.microsoft.com/en-us/library/system.datetime.tolocaltime.aspxźródło
convertedDate.FromLocalTime();
przekonwertuje naUTC
.Wiem, że to starsze pytanie, ale spotkałem się z podobną sytuacją i chciałem podzielić się tym, co znalazłem dla przyszłych poszukiwaczy, w tym również siebie :).
DateTime.Parse()
może być trudne - patrz tutaj na przykład.Jeśli
DateTime
pochodzi z usługi sieci Web lub innego źródła o znanym formacie, możesz rozważyć coś takiegolub nawet lepiej
AssumeUniversal
Flaga informuje parser, że data / czas jest już UTC; kombinacjaAssumeUniversal
iAdjustToUniversal
mówi, aby nie konwertował wyniku na czas „lokalny”, co spróbuje wykonać domyślnie. (Osobiście staram się radzić sobie wyłącznie z UTC w warstwie biznesowej / aplikacji / usług. Ale obejście konwersji na czas lokalny również przyspiesza - o 50% lub więcej w moich testach, patrz poniżej.)Oto, co robiliśmy wcześniej:
Wyprofilowaliśmy aplikację i stwierdziliśmy, że DateTime.Parse reprezentuje znaczny procent wykorzystania procesora. (Nawiasem mówiąc,
CultureInfo
konstruktor nie miał znaczącego wpływu na użycie procesora).Skonfigurowałem więc aplikację konsolową do analizowania ciągu daty / godziny 10000 razy na różne sposoby. Konkluzja:
Parse()
10 sekundParseExact()
(konwersja na lokalną) 20-45 msParseExact()
(bez konwersji na lokalną) 10-15 ms... i tak, wyniki dla
Parse()
są w sekundach , podczas gdy pozostałe są w milisekundach .źródło
Chciałbym tylko dodać ogólną nutę ostrożności.
Jeśli wszystko, co robisz, to pobiera bieżącą godzinę z wewnętrznego zegara komputera, aby umieścić datę / czas na wyświetlaczu lub w raporcie, wszystko jest w porządku. Ale jeśli zapisujesz informacje o dacie / godzinie do późniejszego wykorzystania lub obliczasz datę / czas, strzeż się!
Załóżmy, że ustaliłeś, że statek wycieczkowy przybył do Honolulu w dniu 20 grudnia 2007 r. O 15:00 UTC. I chcesz wiedzieć, co to był czas lokalny.
1. W grę wchodzi prawdopodobnie co najmniej trzech „mieszkańców”. Lokalny może oznaczać Honolulu lub może oznaczać lokalizację komputera lub lokalizację klienta.
2. Jeśli użyjesz wbudowanych funkcji do wykonania konwersji, prawdopodobnie będzie źle. Wynika to z faktu, że czas letni jest (prawdopodobnie) obecnie na twoim komputerze, ale NIE obowiązywał w grudniu. Ale Windows tego nie wie ... wszystko, co ma, to jedna flaga, aby ustalić, czy obowiązuje czas letni. A jeśli to obowiązuje, to z radością doda godzinę nawet do daty w grudniu.
3)Czas letni jest wdrażany inaczej (lub wcale) w różnych działach politycznych. Nie myśl, że tylko dlatego, że twój kraj zmienia się w określonym dniu, inne kraje też.
źródło
źródło
Nie zapomnij, jeśli masz już obiekt DateTime i nie masz pewności, czy jest to obiekt UTC czy lokalny, wystarczy użyć metod bezpośrednio na obiekcie:
O ile nie określono inaczej .net użyje lokalnych ustawień komputera. Przeczytałbym: http://msdn.microsoft.com/en-us/library/system.globalization.daylighttime.aspx
Wyglądem może wyglądać kod:
I jak wspomniano powyżej, sprawdź dwukrotnie, jakie ustawienie strefy czasowej jest ustawiony na serwerze. W sieci znajdują się artykuły dotyczące bezpiecznego wpływu na zmiany w IIS.
źródło
W odpowiedzi na sugestię Dany:
Przykładowy kod wygląda teraz tak:
Pierwotna data to 20/08/08; tego rodzaju był UTC.
Zarówno „convertDate”, jak i „dt” są takie same:
21/08/08 10:00:26; ten rodzaj był lokalny
źródło
Miałem problem z tym, że znajdował się on w zestawie danych przepychanym przez sieć (usługa internetowa do klienta), który to zmieniłby się automatycznie, ponieważ pole DateType DataColumn było ustawione na lokalne. Upewnij się, że sprawdzasz, jaki jest DateType, jeśli przesuwasz DataSets w poprzek.
Jeśli nie chcesz, aby to się zmieniało, ustaw na Nieokreślone
źródło
Natknąłem się na to pytanie, ponieważ miałem problem z datami UTC, które otrzymałeś przez interfejs API Twittera (pole create_at w stanie); Muszę przekonwertować je na DateTime. Żadna z odpowiedzi / próbek kodu w odpowiedziach na tej stronie nie była wystarczająca, aby powstrzymać mnie przed otrzymaniem błędu „Ciąg nie został rozpoznany jako prawidłowy parametr DateTime” (ale jest to najbliższy sposób znalezienia poprawnej odpowiedzi na SO)
Opublikowanie tego linku tutaj na wypadek, gdyby to pomogło komuś innemu - odpowiedź, której potrzebowałem, została znaleziona na tym blogu: http://www.wduffy.co.uk/blog/parsing-dates-when-aspnets-datetimeparse-doesnt-work/ - w zasadzie użyj DateTime.ParseExact z ciągiem formatu zamiast DateTime.Parse
źródło