2013-03-18 17 views
5

Pracuję nad oprogramowaniem, które uruchamia raporty dla urządzeń GPS, które działają 24/7/365. Część danych wyjściowych raportu wymaga, abyśmy konwertowali przechowywane czasy bazy danych (przechowywane w centralnym czasie standardowym) na czasomierze użytkowników (każda żądana strefa czasowa). Dwa razy w roku napotykamy na problem z DST, gdy ludzie uruchamiają raporty, które zaczynają się przed i kończą po zmianie czasu. To nie w jednej linii:Konwertowanie DateTimes w pobliżu oszczędności Daylight Daylight?

return TimeZoneInfo.ConvertTime(dateToConvert, DatabaseTime, UserTime); 

dateToConvert jest DateTime zostać przekształcony. DatabaseTime i UserTime są obiektami TimeZoneInfo. Nie robię niczego skomplikowanego ani skomplikowanego, ale DateTimes w pobliżu wyjątków czasu zmiany czasu DST. Takich jak 3/10/2013 2:02:11 AM, mimo że jest "konwertowany" z czasu centralnego na czas centralny.

Jaka jest najlepsza metoda obsługi DateTimes w pobliżu zmian czasu DST?

+3

To prawdopodobnie więcej przeróbek niż chcesz, ale lepiej byłoby przechowywać wszystkie daty/czasy w GMT (ponieważ CST przechodzi zmianę czasu letniego, są nieciągłości w skali, których nie ma w GMT) i tylko konwertować do celów wyświetlania (a także konwertować parametry wejściowe). – twalberg

+0

Jeśli zaczynałem od zera, zdecydowanie bym to zrobił. Podoba mi się pomysł, aby dane były jak najbardziej neutralne i myślę, że byłby to sposób na zrobienie tego. –

+0

Wystarczy, aby potwierdzić: Czy możliwe jest zapisanie '3/10/2013 2:02:11 AM' w bazie danych, biorąc pod uwagę, że znajduje się ona w pominiętej godzinie? –

Odpowiedz

1

Konwersja powinna działać prawidłowo, ponieważ czas nie jest naprawdę rupieciarski, jak stwierdził Hans, a raczej jest po prostu nieskonfigurowany (termin, który właśnie wymyśliłem). 3/10/2013 2:02:11 AM CDT == 3/10/2013 8:02:11 AM UTC == 3/10/2013 3:02:11 AM CDT ... wszystkie są semantycznie równoważne. Jeśli mi nie wierzysz, zrób konwersję pod numerem timeanddate.com i zobacz, jak wszystkie są równoznaczne (zaokrąglanie do najbliższej 5 minut dla ich kalkulatora). Niezależnie od tego, czy kod .NET pozwoli na tę semantyczną równoważność, nie próbowałem go, ponieważ nie jestem obecnie przed moim dev boxem.

Aktualizacja # 1:

Uruchom następujący kod na komputerze ustawiony na CST strefa czasu:

using System; 

namespace TimeZoneSample 
{ 
    public static class Program 
    { 
     public static void Main() 
     { 
      DateTime t = DateTime.Parse("3/10/2013 2:02:11 AM"); 
      Console.WriteLine(t); 
      Console.WriteLine(t.ToUniversalTime()); 
      Console.WriteLine(t.ToUniversalTime().ToLocalTime()); 
     } 
    } 
} 

Daje to następujące wyjścia konsoli:

3/10/2013 2:02:11 AM 
3/10/2013 8:02:11 AM 
3/10/2013 3:02:11 AM 

Dowód, że moim egzemplarzu wyjaśnienie jest poprawne. quod erat demonstrandum

+0

Zgadzam się i jestem całkowicie z wami, ale .Net's DateTime wydaje się nie działać w ten sposób. –

+0

Zgodnie z twoją edycją, która działa, gdy wstrzymuję debuggera i wstawiam go na listę Watch, ale kiedy kod faktycznie próbuje wykonać 'return TimeZoneInfo.ConvertTime (dateToConvert.ToUniversalTime(). ToLocalTime(), DatabaseTime, UserTime); 'Otrzymuję komunikat o błędzie mówiąc, że' DatabaseTime' musi być 'TimeZoneInfo.Local'. Nie wiem, czy to akceptowalne założenie w naszym systemie. –

+0

Rozmawiałem z moim zespołem. Okazuje się, że jest to wystarczająco bezpieczne założenie, ponieważ prowadzimy własne serwery. –

3

Wpadłem na ten problem. Naprawiłem to, dodając nową kolumnę czasu GMT. Pozwoliło to aplikacji pracować z oryginalnymi danymi i wszelkimi poprawkami do pracy z GMT. Następnie zmieniłem aplikację, aby dowolny kod, który miał problemy z dostępnością światła dziennego, miałby dostęp do tej nowej kolumny. Ponadto, w miarę upływu czasu, ponownie wskazałem dowolny kod, który został użyty do obliczeń do tej nowej kolumny, pozostawiając ekrany do pracy ze starą kolumną. To nie jest eleganckie, ale działa i jest łatwe.

4

Masz śmieci w swojej bazie danych, 3.10.2013 2:02:11 Nigdy nie istniał. Minuta po 01:59 rano tego ranka była o 3:00, zegar został przesunięty o godzinę. .NET nie będzie tolerować tej śmieciowej daty.

Będziesz musiał dowiedzieć się, jak ten znacznik czasu śmieci zakończył się w twojej dbase. Oczywiście wysoce prawdopodobnym źródłem tych śmieci jest konwersja czasu z jednej strefy czasowej na inną, która lekceważy zasady dotyczące światła dziennego, takie jak aktywne w jednym, ale nie drugim. Jeśli nie możesz naprawić swojej bazy danych, aby użyć UTC, to zrób to przynajmniej w swoim kodzie. Najpierw przejście do UTC w jednej strefie czasowej, a następnie powrót do czasu lokalnego w drugiej. Użyj metod klasy TimeZoneInfo, ConvertTimeFrom/ToUtc.

+0

Kod zaplecza, który pobiera wpisy GPS i przesyła je do bazy danych, jest napisany w VB6 (Nienawidzę tego i nie mogę się doczekać, aż wprowadzimy zmiany C#) i myślę, że być może nasz VB6 nie zapłacił wystarczająco zwracanie uwagi na czas letni podczas obliczeń. –

+0

Tak, jest ** bardzo ** mało prawdopodobne, że backend VB6 mógłby to naprawić. –

1

chciałbym wykonać jedną z innych odpowiedzi, czy to w ogóle możliwe - chcesz naprawić to poprawnie. Jeśli twój czas jest niepoprawny podczas przejścia na jesień, to nie wygeneruje wyjątku, tylko losowo będzie godzina.

Istnieje obejście pozwalające wydostać się z obecnego zacięcia.Ponieważ tylko brakująca godzina podczas wiosny spowoduje wyjątek, możesz złapać wyjątek i dodać godzinę przed powtórzeniem konwersji.

+0

Przez ostatnie pół godziny bawiło mnie to jako szybkie rozwiązanie. –

Powiązane problemy