Najlepsze praktyki dotyczące czasu i strefy czasowej w czasie letnim [zamknięte]


2046

Mam nadzieję, że to pytanie i odpowiedzi na nie będą definitywnym przewodnikiem radzenia sobie z czasem letnim, w szczególności z faktycznym przestawieniem się na zmianę.

Jeśli masz coś do dodania, zrób to

Wiele systemów zależy od utrzymywania dokładnego czasu, problemem są zmiany czasu wynikające z oszczędności czasu dziennego - przesunięcie zegara do przodu lub do tyłu.

Na przykład, istnieją reguły biznesowe w systemie przyjmowania zamówień, które zależą od czasu zamówienia - jeśli zegar się zmieni, reguły mogą nie być tak jasne. Jak należy zachować czas zamówienia? Istnieje oczywiście nieskończona liczba scenariuszy - ten jest po prostu ilustracyjny.

  • Jak poradziłeś sobie z problemem czasu letniego?
  • Jakie założenia są częścią twojego rozwiązania? (szuka kontekstu tutaj)

Co ważne, jeśli nie bardziej:

  • Co próbowałeś, że nie zadziałało?
  • Dlaczego to nie zadziałało?

Byłbym zainteresowany programowaniem, systemem operacyjnym, trwałością danych i innymi istotnymi aspektami tego problemu.

Ogólne odpowiedzi są świetne, ale chciałbym również zobaczyć szczegóły, zwłaszcza jeśli są dostępne tylko na jednej platformie.


2
@abatishchev - W ten sposób GETDATE()na SQL będzie UTC (jak będzie DateTime.Now). Serwer nie będzie miał wpływu na żadne automatyczne zmiany czasu letniego.
Oded

4
@Oded: Zgadzam się, czy zostanie dodane „na serwerze”. Ale nadal może to wpływać na inne aplikacje wymagające czasu lokalnego. Z tego i innych powodów uważam, że lepiej jest poprosić o czas Utc wyraźnie.
abatishchev

7
UTC jest lepszy niż GMT, zarówno dlatego, że jest bardziej precyzyjnie zdefiniowany, jak i dlatego, że definicje GMT są pomieszane w niektórych systemach operacyjnych. Ludzie często traktują terminy „GMT” i „UTC” jako wymienne, ale nie do końca. Do prawie wszystkich celów oprogramowania / systemów używaj UTC. Zobacz stackoverflow.com/questions/2292334/...
Chris Johnson

7
@JoshStodola - „ Odpowiedź ” Jona Skeeta .
Kenny Evitt,

1
@ Nie możesz zakładać, że serwer będzie na UTC, widziałem serwery produkcyjne, w których strefą czasową był „UTC”, ale zastosowałem DST, więc tak naprawdę było UTC + 1 przez ponad pół roku. Zgadzam się z @abatishchev, aby być jawnym i używać, DateTime.UtcNowa GETUTCDATE()także pokazuje innym deweloperom, że tak naprawdę o tym
myślałeś

Odpowiedzi:


940

Podsumowanie odpowiedzi i innych danych: (proszę dodać swoje)

Zrobić:

  • Ilekroć masz na myśli konkretny moment w czasie, zachowaj czas zgodnie ze zunifikowanym standardem, na który nie mają wpływu oszczędności czasu. (GMT i UTC są równoważne pod tym względem, ale lepiej jest używać terminu UTC. Zauważ, że UTC jest również znany jako czas Zulu lub Z. )
  • Jeśli zamiast tego zdecydujesz się zachować czas przy użyciu wartości czasu lokalnego, uwzględnij przesunięcie czasu lokalnego dla tego konkretnego czasu względem UTC (przesunięcie to może się zmieniać w ciągu roku), tak aby znacznik czasu mógł być później interpretowany jednoznacznie.
  • W niektórych przypadkach może być konieczne zapisanie zarówno czasu UTC, jak i równoważnego czasu lokalnego. Często odbywa się to za pomocą dwóch oddzielnych pól, ale niektóre platformy obsługują datetimeoffsettyp, który może przechowywać oba w jednym polu.
  • Przechowując znaczniki czasu jako wartość liczbową, używaj czasu uniksowego - który jest liczbą pełnych sekund od 1970-01-01T00:00:00Z(z wyłączeniem sekund przestępnych). Jeśli potrzebujesz większej precyzji, użyj zamiast tego milisekund. Wartość ta powinna zawsze opierać się na UTC, bez zmiany strefy czasowej.
  • Jeśli później będziesz musiał zmodyfikować znacznik czasu, dołącz oryginalny identyfikator strefy czasowej, aby określić, czy przesunięcie mogło ulec zmianie w stosunku do zarejestrowanej pierwotnej wartości.
  • Podczas planowania przyszłych zdarzeń preferowany jest zwykle czas lokalny zamiast UTC, ponieważ zmiana przesunięcia często występuje. Zobacz odpowiedź i post na blogu .
  • Podczas przechowywania całych dat, takich jak urodziny i rocznice, nie przechodź na UTC ani żadną inną strefę czasową.
    • Jeśli to możliwe, przechowuj dane tylko z datą, która nie obejmuje pory dnia.
    • Jeśli taki typ nie jest dostępny, należy zawsze ignorować porę dnia podczas interpretacji wartości. Jeśli nie możesz być pewien, że pora dnia zostanie zignorowana, wybierz 12:00 12:00 zamiast 00:00 Północ jako bardziej bezpieczny czas reprezentatywny tego dnia.
  • Pamiętaj, że przesunięcia stref czasowych nie zawsze są liczbą całkowitą godzin (na przykład czas standardowy w Indiach to UTC + 05: 30, a Nepal używa UTC + 05: 45).
  • Jeśli używasz Java, użyj java.time dla Java 8 i nowszych.
  • Jeśli używasz platformy .NET , rozważ użycie czasu Noda .
  • Jeśli używasz .NET bez Noda Time, zastanów się, że DateTimeOffsetczęsto jest to lepszy wybór niż DateTime.
  • Jeśli używasz Perla, użyj DateTime .
  • Jeśli używasz Python, użyj pytz lub dateutil .
  • Jeśli używasz JavaScript, użyj moment.js z rozszerzeniem strefy czasowej .
  • Jeśli używasz PHP> 5.2, użyj natywnych konwersji stref czasowych dostarczonych przez DateTimei DateTimeZoneklas. Zachowaj ostrożność podczas używania DateTimeZone::listAbbreviations()- patrz odpowiedź . Aby zachować PHP z aktualność Olson danych, należy zainstalować okresowo na timezonedb pakiet PECL; patrz odpowiedź .
  • Jeśli używasz C ++, pamiętaj, aby użyć biblioteki, która używa poprawnie implementuje bazę danych strefy czasowej IANA . Należą do nich cctz , ICU i biblioteka „tz” Howarda Hinnanta .
    • Nie używaj wzmocnienia do konwersji stref czasowych. Chociaż jego interfejs API twierdzi, że obsługuje standardowe identyfikatory IANA (znane również jako „zoneinfo”), to w przybliżeniu mapuje je na dane w stylu POSIX, bez uwzględnienia bogatej historii zmian, które mogły mieć poszczególne strefy. (Ponadto plik wypadł z konserwacji).
  • Jeśli używasz Rust, użyj chrono .
  • Większość reguł biznesowych używa czasu cywilnego, a nie UTC lub GMT. Dlatego przed zastosowaniem logiki aplikacji należy zaplanować konwersję znaczników czasu UTC na lokalną strefę czasową.
  • Pamiętaj, że strefy czasowe i przesunięcia nie są stałe i mogą ulec zmianie. Na przykład w przeszłości USA i Wielka Brytania używały tych samych dat do „skoku do przodu” i „wycofania się”. Jednak w 2007 r. USA zmieniły daty, w których zmieniają się zegary. Oznacza to teraz, że przez 48 tygodni w roku różnica między czasem londyńskim a nowojorskim wynosi 5 godzin, a przez 4 tygodnie (3 wiosną, 1 jesienią) 4 godziny. Pamiętaj o takich elementach we wszelkich obliczeniach, które dotyczą wielu stref.
  • Zastanów się, jaki rodzaj czasu (rzeczywisty czas zdarzenia, czas emisji, czas względny, czas historyczny, cykliczny), jakie elementy (znacznik czasu, przesunięcie strefy czasowej i nazwa strefy czasowej) należy zapisać w celu prawidłowego wyszukiwania - patrz „Rodzaje czasu” w ta odpowiedź .
  • Synchronizuj pliki tzdata systemu operacyjnego, bazy danych i aplikacji między sobą i resztą świata.
  • Na serwerach ustaw zegary sprzętowe i zegary systemu operacyjnego na UTC zamiast na lokalną strefę czasową.
  • Niezależnie od poprzedniego punktu, kod po stronie serwera, w tym strony internetowe, nigdy nie powinien oczekiwać, że lokalna strefa czasowa serwera będzie czymś szczególnym. patrz odpowiedź .
  • Wolisz pracować ze strefami czasowymi dla poszczególnych przypadków w kodzie aplikacji, zamiast globalnie poprzez ustawienia pliku konfiguracyjnego lub ustawienia domyślne.
  • Korzystaj z usług NTP na wszystkich serwerach.
  • Jeśli używasz FAT32 , pamiętaj, że znaczniki czasu są przechowywane w czasie lokalnym, a nie UTC.
  • W przypadku powtarzających się wydarzeń (na przykład cotygodniowego programu telewizyjnego) pamiętaj, że czas zmienia się wraz z czasem letnim i będzie różny w różnych strefach czasowych.
  • Zawsze sprawdzaj wartości daty i godziny jako dolne ograniczenie włącznie, górne ograniczenie wyłączności ( >=, <).

Nie:

  • Nie należy mylić „strefy czasowej”, na przykład America/New_Yorkz „przesunięciem strefy czasowej”, np -05:00. To są dwie różne rzeczy. Zobacz wiki tagu strefy czasowej .
  • Nie używaj Dateobiektu JavaScript do wykonywania obliczeń daty i godziny w starszych przeglądarkach internetowych, ponieważ ECMAScript 5.1 i nowsze mają wadę projektową, która może nieprawidłowo wykorzystywać czas letni. (Zostało to naprawione w ECMAScript 6/2015).
  • Nigdy nie ufaj zegarowi klienta. To może być bardzo niepoprawne.
  • Nie mów ludziom, by „zawsze korzystali z UTC wszędzie”. Ta szeroko rozpowszechniona rada zawiera krótką wizję kilku ważnych scenariuszy opisanych wcześniej w tym dokumencie. Zamiast tego użyj odpowiedniego odniesienia czasu dla danych, z którymi pracujesz. ( Znaczniki czasu mogą korzystać z UTC, ale harmonogramy przyszłych wartości i wartości tylko daty nie powinny.)

Testowanie:

  • Podczas testowania upewnij się, że testujesz kraje na półkuli zachodniej, wschodniej, północnej i południowej (w rzeczywistości w każdej ćwiartce globu, a więc w 4 regionach), przy czym zarówno DST jest w toku, jak i nie (daje 8), oraz kraj, który ma nie używaj DST (kolejne 4, aby objąć wszystkie regiony, co daje w sumie 12).
  • Przetestuj przejście DST, tzn. Gdy jesteś w okresie letnim, wybierz wartość czasu z zimy.
  • Testuj przypadki graniczne, takie jak strefa czasowa UTC + 12 z DST, dzięki czemu czas lokalny UTC + 13 latem, a nawet miejsca, które są UTC + 13 zimą
  • Przetestuj wszystkie biblioteki i aplikacje innych firm i upewnij się, że poprawnie obsługują dane strefy czasowej.
  • Testuj co najmniej półgodzinne strefy czasowe.

Odniesienie:

Inny:

  • Lobbuj swojego przedstawiciela, aby zakończyć obrzydliwość DST. Zawsze możemy mieć nadzieję ...
  • Lobby dla czasu standardowego Ziemi

31
Korzystanie z GMT tak naprawdę nie rozwiązuje problemu, wciąż musisz dowiedzieć się, jaka jest właściwa delta do zastosowania, i tutaj leży cała złożoność. Delta może być złożona do określenia w systemach używanych przez użytkowników w różnych regionach (z różnymi harmonogramami przełączników czasu letniego) lub w systemach pokazujących dane historyczne / przyszłe.
ckarras

10
To prawda, jeśli aplikacja musi tylko wyświetlić bieżący czas lokalny. Ale jeśli mamy na przykład serwer w Australii, który musi wyświetlać datę / godzinę transakcji w Kanadzie w dniu 2 kwietnia 2006 r. (To był ostatni rok przed zmianą reguł przełączania czasu letniego w Kanadzie) - czy masz połączenie z systemem operacyjnym które mogą zrobić DateTime („2006/04/02 14: 35Z”). ToLocalTime (). WithDaylightSavingRules („Kanada”, 2006)?
ckarras

22
Tak, w systemie Windows istnieje takie wywołanie systemu operacyjnego - SystemTimeToTzSpecificLocation. msdn.microsoft.com/en-us/library/ms724949(VS.85).aspx
Michael Madsen

7
@ tchrist Może jeśli jesteś wytrwały, możesz.
Peter Ajtai

16
Pamiętaj, przekształcając przyszłe daty (nawet tylko jutro) w UTC, zawsze coś tracisz. Na przykład użyłeś znanego przesunięcia, aby dokonać tej konwersji, ale ponieważ data jest w przyszłości, zawsze istnieje szansa, że ​​grupa, która ustanowi te reguły, zmieni te reguły. Poza tym konwersja niektórych przyszłych dat na UTC jest praktycznie niemożliwa, ponieważ czasy oszczędności w ciągu dnia nie są znane do tego roku (niektóre kraje ustalają daty co roku, nie więcej niż 10 lat wcześniej lub na podstawie ustalonych zasad).
eselk

319

Nie jestem pewien, co mogę dodać do powyższych odpowiedzi, ale oto kilka punktów ode mnie:

Rodzaje czasów

Należy wziąć pod uwagę cztery różne czasy:

  1. Czas wydarzenia: np. Czas, kiedy ma miejsce międzynarodowa impreza sportowa lub koronacja / śmierć / itp. Zależy to od strefy czasowej wydarzenia, a nie od widza.
  2. Czas telewizyjny: np. Określony program telewizyjny jest emitowany o 21:00 czasu lokalnego na całym świecie. Ważne, gdy myślisz o opublikowaniu wyników (np. American Idol) na swojej stronie internetowej
  3. Czas względny: np .: To pytanie ma otwarte zamknięcie nagrody w ciągu 21 godzin. Jest to łatwe do wyświetlenia
  4. Powtarzający się czas: np .: program telewizyjny jest w każdy poniedziałek o 21:00, nawet jeśli zmienia się czas letni.

Jest też czas historyczny / alternatywny. Są denerwujące, ponieważ mogą nie odwzorować czasu standardowego. Np .: daty juliańskie, daty według kalendarza księżycowego na Saturnie, kalendarz Klingona.

Przechowywanie znaczników czasu rozpoczęcia / zakończenia w UTC działa dobrze. Dla 1 potrzebujesz nazwy strefy czasowej zdarzenia + przesunięcia zapisanej wraz ze zdarzeniem. W przypadku 2 potrzebujesz lokalnego identyfikatora czasu zapisanego dla każdego regionu oraz lokalnej nazwy strefy czasowej + przesunięcia zapisanego dla każdej przeglądarki (możesz uzyskać to z adresu IP, jeśli jesteś w kryzysie). Dla 3, przechowuj w UTC sekundach i nie potrzebujesz stref czasowych. 4 to szczególny przypadek 1 lub 2, w zależności od tego, czy jest to wydarzenie globalne, czy lokalne, ale musisz także zapisać utworzony znacznik czasu, aby można było stwierdzić, czy definicja strefy czasowej uległa zmianie przed utworzeniem tego zdarzenia, czy po nim. Jest to konieczne, jeśli chcesz pokazać dane historyczne.

Czas przechowywania

  • Zawsze przechowuj czas w UTC
  • Konwertuj na wyświetlany czas lokalny (lokalny jest definiowany przez użytkownika patrząc na dane)
  • Podczas przechowywania strefy czasowej potrzebujesz nazwy, znacznika czasu i przesunięcia. Jest to wymagane, ponieważ rządy czasami zmieniają znaczenie swoich stref czasowych (np. Rząd USA zmienił daty DST), a twoja aplikacja musi z wdziękiem sobie z tym poradzić ... np .: Dokładny znacznik czasu, w którym odcinki LOST były wyświetlane zarówno przed, jak i po regułach DST zmienione.

Przesunięcia i nazwy

Przykładem powyższego byłoby:

Mecz finałów mistrzostw świata w piłce nożnej odbył się w Afryce Południowej (UTC + 2 - SAST) w dniu 11 lipca 2010 r. O godzinie 19:00 UTC.

Dzięki tym informacjom możemy historycznie określić dokładny czas, w którym miały miejsce finały WCS 2010, nawet jeśli zmieni się definicja strefy czasowej w RPA, i będziemy w stanie wyświetlić ją widzom w ich lokalnej strefie czasowej w momencie, gdy przeszukują bazę danych.

Czas systemu

Musisz także zsynchronizować pliki tzdata systemu operacyjnego, bazy danych i aplikacji, zarówno ze sobą, jak i z resztą świata, i przeprowadzić intensywne testy podczas aktualizacji. Nie jest niczym niezwykłym, że aplikacja innej firmy, na której polegasz, nie obsługiwała poprawnie zmiany TZ.

Upewnij się, że zegary sprzętowe są ustawione na UTC, a jeśli korzystasz z serwerów na całym świecie, upewnij się, że ich systemy operacyjne są skonfigurowane do korzystania z UTC. Staje się to widoczne, gdy trzeba kopiować co godzinę obrócone pliki dziennika apache z serwerów w wielu strefach czasowych. Sortowanie ich według nazwy pliku działa tylko wtedy, gdy wszystkie pliki mają taką samą strefę czasową. Oznacza to również, że nie musisz wykonywać obliczeń matematycznych w swojej głowie, gdy ssh z jednego pola do drugiego i musisz porównać znaczniki czasu.

Ponadto uruchom ntpd na wszystkich polach.

Klienci

Nigdy nie ufaj znacznikowi czasu, który otrzymujesz z komputera klienckiego jako prawidłowy. Na przykład nagłówki Date: HTTP lub Date.getTime()wywołanie javascript . Są one odpowiednie, gdy są używane jako nieprzezroczyste identyfikatory lub podczas obliczania matematycznego podczas jednej sesji na tym samym kliencie, ale nie próbuj odwoływać się do tych wartości z czymś, co masz na serwerze. Twoi klienci nie korzystają z NTP i niekoniecznie mają działającą baterię dla zegara BIOS.

Drobnostki

Wreszcie rządy czasami robią bardzo dziwne rzeczy:

Standardowy czas w Holandii wynosił dokładnie 19 minut i 32,13 sekundy przed UTC zgodnie z prawem od 1909-05-01 do 1937-06-30. Tej strefy czasowej nie można dokładnie przedstawić przy użyciu formatu GG: MM.

Ok, chyba skończone.


6
Ta odpowiedź ma kilka świetnych punktów, szczególnie chciałem zwrócić uwagę na tę część „Cykliczny czas: np .: program telewizyjny jest w każdy poniedziałek o 9 wieczorem, nawet gdy zmienia się czas letni” Przechowywanie czasów w UTC w DB, a następnie konwersja do wyświetlania pomaga poradzić sobie wiele trudnych aspektów radzenia sobie ze strefami czasowymi. Jednak obsługa „powtarzających się zdarzeń”, które przekraczają bariery DST, staje się znacznie trudniejsza.
Jared Hales,

45
+1 za Ciekawostki. Zachowanie interesującej zawartości sprawia, że ​​to zadanie jest przyjemniejsze, co może prowadzić do zwiększenia wydajności :)
Chris

4
W tej odpowiedzi jest wiele dobrych rzeczy, ale kilka problemów. 1) Wiele skrótów stref czasowych jest niejednoznacznych. patrz tutaj 2) Nie zawsze chcesz przechowywać w UTC. Przez większość czasu - tak, ale kontekst ma znaczenie. W twoim rozumieniu czas telewizyjny nie byłby przechowywany w UTC. Czasami niezgodne z prawem lub niezgodne z polityką jest nieprzechowywanie czasu lokalnego - w takich sytuacjach DateTimeOffsetprzydaje się coś takiego (lub równoważny). W przeciwnym razie dobrze napisz.
Matt Johnson-Pint

1
Tak więc wszyscy zgadzają się, że biblioteka Joda jest zdecydowanie najlepszym dostępnym narzędziem do tego zadania. Musimy jednak aktualizować (przebudowywać) plik jar JODA zgodnie z tym artykułem ( joda.org/joda-time/tz_update.html ), aby być na bieżąco z najnowszymi informacjami o strefie czasowej. Czy istnieje jakiś standardowy sposób pobierania najnowszych danych strefy czasowej ze strony IANA ( iana.org/time-zones ) i przebudowywania biblioteki Joda? Innymi słowy, czy można zautomatyzować ten proces zamiast robić to ręcznie?
saravana_pc

2
Ciekawostki z Holandii wyglądają legalnie. ietf.org/rfc/rfc3339.txt sekcja 5.8. W połowie drogi doszedł do wniosku, że ktoś ciągnie nas za nogę.
ruffin

89

To ważna i zaskakująco trudna sprawa. Prawda jest taka, że ​​nie ma całkowicie zadowalającego standardu utrzymywania czasu. Na przykład standard SQL i format ISO (ISO 8601) są zdecydowanie niewystarczające.

Z koncepcyjnego punktu widzenia zwykle mamy do czynienia z dwoma typami danych daty i godziny i wygodnie jest je rozróżnić (powyższe standardy tego nie robią): „ czas fizyczny ” i „ czas cywilny ”.

„Fizyczna” chwila czasu jest punktem w ciągłej uniwersalnej linii czasu, z którym ma do czynienia fizyka (oczywiście ignorując teorię względności). Ta koncepcja może być odpowiednio zakodowana i utrwalona na przykład w UTC (jeśli możesz zignorować sekundy przestępne).

Czas „cywilny” to specyfikacja daty i godziny zgodna z normami cywilnymi: moment w tym miejscu jest w pełni określony przez zestaw pól daty i godziny (Y, M, D, H, MM, S, FS) plus TZ (specyfikacja strefy czasowej) (tak naprawdę „kalendarz”, ale załóżmy, że ograniczamy dyskusję do kalendarza gregoriańskiego). Strefa czasowa i kalendarz łącznie pozwalają (w zasadzie) na mapowanie jednej reprezentacji do drugiej. Ale instancje czasu cywilnego i fizycznego są zasadniczo różnymi rodzajami wielkości i należy je koncepcyjnie oddzielić i traktować inaczej (analogia: tablice bajtów i ciągów znaków).

Kwestia ta jest myląca, ponieważ mówimy o tego rodzaju wydarzeniach zamiennie, a ponieważ czasy cywilne podlegają zmianom politycznym. Problem (i potrzeba rozróżnienia tych pojęć) staje się bardziej widoczny dla wydarzeń w przyszłości. Przykład (wzięty z mojej dyskusji tutaj .

John zapisuje w swoim kalendarzu przypomnienie o pewnym wydarzeniu w czasie 2019-Jul-27, 10:30:00, TZ = Chile/Santiago, (które przesunęło GMT-4, a zatem odpowiada UTC 2019-Jul-27 14:30:00). Ale któregoś dnia w przyszłości kraj postanawia zmienić przesunięcie TZ na GMT-5.

Teraz, kiedy nadejdzie dzień ... czy to przypomnienie powinno się uruchomić

A) 2019-Jul-27 10:30:00 Chile/Santiago = UTC time 2019-Jul-27 15:30:00?

lub

B) 2019-Jul-27 9:30:00 Chile/Santiago = UTC time 2019-Jul-27 14:30:00?

Nie ma poprawnej odpowiedzi, chyba że ktoś wie, co John miał na myśli, mówiąc do kalendarza „Proszę o telefon 2019-Jul-27, 10:30:00 TZ=Chile/Santiago”.

Czy miał na myśli „cywilną datę i godzinę” („kiedy zegary w moim mieście mówią o 10:30”)? W takim przypadku A) jest prawidłową odpowiedzią.

Czy też miał na myśli „fizyczną chwilę czasu”, punkt w ciągłej linii czasu naszego wszechświata, powiedzmy „kiedy nastąpi następne zaćmienie Słońca”. W takim przypadku odpowiedź B) jest poprawna.

Kilka interfejsów API Data / Czas dobrze to rozróżnia: wśród nich Jodatime , który jest podstawą następnego (trzeciego!) Interfejsu Java DateTime API (JSR 310).


1
Inną kwestią do rozważenia, której nie widziałem w interfejsach API, jest to, że nawet jeśli podano czas i strefę czasową, istnieją co najmniej dwa prawdopodobne znaczenia dla np. „13: 00: 00EDT”. Może to odnosić się do czegoś, o czym wiadomo, że nastąpiło o godzinie 13:00 czasu lokalnego, który uważano za wschodni czas letni, lub do czegoś, o czym wiadomo, że nastąpił w chwili, gdy czas wschodni osiągnął 13:00, co uważa się za miały miejsce w miejscu obserwującym wschodni czas letni. Jeśli ktoś ma wiele znaczników czasu, gdzie informacji strefy czasowej może być źle (np pliki aparatów cyfrowych) ...
Supercat

1
... wiedza o tym, czy odzwierciedlają dokładny czas lokalny czy globalny, może być ważna przy ustalaniu sposobu ich skorygowania.
supercat

3
Najwyraźniej John chce A), ponieważ ludzie idą do pracy o 8:30, bez względu na czas letni lub strefę czasową. Jeśli wejdą w czas letni, pójdą do pracy o 8:30, kiedy wyjdą z czasu letniego, pójdą do pracy o 8:30. Jeśli kraj zdecyduje się przenieść do innej strefy czasowej, pójdzie do pracy o 8:30 w każdy wieczór
Gianluca Ghettini

59

Dokonaj wyraźnego architektonicznego rozdzielenia obaw - aby dokładnie wiedzieć, który poziom współdziała z użytkownikami, i musisz zmienić datę i godzinę dla reprezentacji kanonicznej (UTC). Data poza czasem UTC jest prezentacją (podąża za lokalną strefą czasową użytkowników), czas UTC jest modelem (pozostaje unikalny dla zaplecza i średnich poziomów).

Zdecyduj też, kim są Twoi odbiorcy, czego nie musisz podawać i gdzie wyznaczasz granice . Nie dotykaj egzotycznych kalendarzy, chyba że faktycznie masz tam ważnych klientów, a następnie rozważ oddzielne serwery skierowane do użytkowników tylko dla tego regionu.

Jeśli możesz uzyskiwać i utrzymywać lokalizację użytkownika, użyj lokalizacji do systematycznej konwersji daty i godziny (powiedzmy kulturę .NET lub tabelę SQL), ale zapewnij użytkownikowi możliwość wyboru zastąpień, jeśli data i czas mają krytyczne znaczenie dla użytkowników.

Jeśli wiążą się z tym historyczne obowiązki kontrolne (np. Dokładne określenie, kiedy Jo w AZ zapłacił rachunek 2 lata temu we wrześniu), zachowaj zarówno UTC, jak i czas lokalny dla rekordu (tabele konwersji zmienią się z czasem).

Zdefiniuj strefę czasową dla danych, które są dostarczane luzem - takie jak pliki, usługi sieciowe itp. Powiedzmy, że firma z wschodniego wybrzeża ma centrum danych w Kalifornii - musisz zapytać i wiedzieć, czego używają jako standardu zamiast zakładać jedno lub drugie.

Nie ufaj przesunięciom strefy czasowej osadzonym w tekstowej reprezentacji daty i godziny i nie akceptuj ich analizowania i śledzenia. Zamiast tego zawsze należy zażądać, aby strefa czasowa i / lub strefa odniesienia musiały być wyraźnie zdefiniowane . Możesz łatwo odbierać czas z przesunięciem PST, ale faktycznie jest to EST, ponieważ jest to czas odniesienia klienta, a rekordy zostały właśnie wyeksportowane na serwer, który jest w PST.


40

Musisz wiedzieć o bazie danych Olson tz , która jest dostępna na ftp://elsie.nci.nih.gov/pub http://iana.org/time-zones/ . Jest aktualizowany wiele razy w roku, aby poradzić sobie ze zmianami w ostatniej chwili, kiedy (i czy), aby przełączać się między zimą a latem (czas standardowy i czas letni) w różnych krajach na całym świecie. W 2009 roku ostatnim wydaniem były lata 2009; w 2010 r. był to rok 2010n; w 2011 roku był to 2011n; pod koniec maja 2012 r. wydano 2012c. Zauważ, że w dwóch osobnych archiwach (tzcode20xxy.tar.gz i tzdata20xxy.tar.gz) znajduje się zestaw kodu do zarządzania danymi i danymi rzeczywistej strefy czasowej. Zarówno kod, jak i dane są w domenie publicznej.

Jest to źródło nazw stref czasowych, takich jak Ameryka / Los_Angeles (i synonimów, takich jak USA / Pacyfik).

Jeśli chcesz śledzić różne strefy, potrzebujesz bazy danych Olson. Jak sugerują inni, chcesz również przechowywać dane w ustalonym formacie - zwykle wybierany jest UTC - wraz z zapisem strefy czasowej, w której dane zostały wygenerowane. Możesz rozróżnić przesunięcie od UTC w czasie od nazwy strefy czasowej; może to później zmienić. Również świadomość, że obecnie jest to 2010-03-28T23: 47: 00-07: 00 (USA / Pacyfik) może, ale nie musi pomóc w interpretacji wartości 2010-11-15T12: 30 - co jest prawdopodobnie określone w PST ( Pacific Standard Time) zamiast PDT (Pacific Daylight Saving Time).

Standardowe interfejsy biblioteki C nie są strasznie pomocne w tego typu sprawach.


Dane Olsona zostały przeniesione, po części dlatego, że AD Olson wkrótce przejdzie na emeryturę, a po części dlatego, że (obecnie odrzucono) pozew przeciwko opiekunom o naruszenie praw autorskich. Baza danych stref czasowych jest teraz zarządzana pod patronatem IANA , Internet Assigned Numbers Authority, a na pierwszej stronie znajduje się link do „Strefy czasowej” . Lista dyskusyjna jest teraz tz@iana.org; lista ogłoszeń jest tz-announce@iana.org.


12
Baza danych Olson zawiera również dane historyczne , co czyni ją szczególnie przydatną do obsługi DST. Na przykład wie, że wartość UTC odpowiadająca 31 marca 2000 r. W USA nie jest w DST, ale wartość UTC odpowiadająca 31 marca 2008 r. W USA to.
Josh Kelley

3
Konsorcjum Unicode utrzymuje mapowanie między identyfikatorami stref tomów Olsona i identyfikatorami stref czasowych Windows: unicode.org/repos/cldr-tmp/trunk/diff/supplemental/...
Josh Kelley

Zaktualizowany link do strony Konsorcjum Unicode: unicode.org/repos/cldr-tmp/trunk/diff/supplemental/…
Span

Gdzie można znaleźć informacje o analizie plików Olsona? Chcę skompilować go w tabeli db, ale nie mogę zrozumieć, jak powinienem czytać pliki
shealtiel,

@gidireich: główne informacje znajdują się w danych i nie są łatwe do zrozumienia. Główna dokumentacja na ten temat znajduje się na zic.8stronie podręcznika (lub zic.8.txt). Będziesz potrzebował tzcode2011i.tar.gzpliku, a nie tzdata2011i.tar.gzpliku, aby uzyskać te informacje.
Jonathan Leffler,

26

Zasadniczo uwzględniaj lokalne przesunięcie czasu (w tym przesunięcie czasu letniego) w przechowywanych znacznikach czasu: sam UTC nie wystarczy, jeśli chcesz później wyświetlić znacznik czasu w oryginalnej strefie czasowej (i ustawieniu czasu letniego).

Należy pamiętać, że przesunięcie nie zawsze jest liczbą całkowitą godzin (np. Czas standardowy w Indiach to UTC + 05: 30).

Na przykład odpowiednimi formatami są krotki (czas uniksowy, przesunięcie w minutach) lub ISO 8601 .


5
Przesunięcie jest idealne do wyświetlania. Jeśli chcesz wprowadzić zmiany, przesunięcie to wciąż za mało. Musisz także znać strefę czasową, ponieważ nowa wartość może wymagać innego przesunięcia.
Matt Johnson-Pint

23

Przekraczanie granic „czasu komputerowego” i „czasu ludzi” to koszmar. Najważniejsze jest to, że nie ma żadnego standardu dla reguł dotyczących stref czasowych i czasu letniego. Kraje mogą dowolnie zmieniać swoją strefę czasową i zasady DST w dowolnym momencie, i robią to.

Niektóre kraje, np. Izrael, Brazylia, co roku decydują o tym, kiedy mają mieć czas letni, więc nie można z góry wiedzieć, kiedy (jeśli) obowiązuje czas letni. Inni mają ustalone (ish) reguły określające, kiedy obowiązuje czas letni. Inne kraje nie stosują DST jak wszystkie.

Strefy czasowe nie muszą być różnicami pełnymi godzinami od GMT. Nepal wynosi +5,45. Istnieją nawet strefy czasowe, które wynoszą +13. Oznacza to, że:

SUN 23:00 in Howland Island (-12)
MON 11:00 GMT 
TUE 00:00 in Tonga (+13)

są wszystkie w tym samym czasie, ale 3 różne dni!

Nie ma też wyraźnego standardu dla skrótów stref czasowych i ich zmiany w DST, więc powstają takie rzeczy:

AST Arab Standard Time     UTC+03
AST Arabian Standard Time  UTC+04
AST Arabic Standard Time   UTC+03

Najlepszą radą jest trzymać się jak najdalej od czasu lokalnego i trzymać się UTC tam, gdzie to możliwe. Przeliczaj na czasy lokalne tylko w ostatnim możliwym momencie.

Podczas testowania upewnij się, że testujesz kraje na zachodniej i wschodniej półkuli, zarówno z DST w toku, jak i nie, oraz z krajem, który nie używa DST (łącznie 6).


W odniesieniu do Izraela - to połowa prawdy. Chociaż czas zmiany czasu letniego nie jest konkretną datą w kalendarzu juliańskim - istnieje reguła oparta na kalendarzu hebrajskim (zmiana nastąpiła w 2014 r.). W każdym razie ogólna idea jest poprawna - te rzeczy mogą się zmieniać i od czasu do czasu
Yaron U.

1
Ponadto AST = czas standardowy Atlantyku. Jeśli chodzi o „najlepszą radę”, jest ona w porządku jako punkt wyjścia, ale musisz przeczytać resztę tej strony i odmówić krótką modlitwę, a może uda ci się to zrobić przez jakiś czas.
DavidWalley,

20

Dla PHP:

Klasa DateTimeZone w PHP> 5.2 jest już oparta na bazie danych Olson, o której wspominają inni, więc jeśli wykonujesz konwersje strefy czasowej w PHP, a nie w DB, jesteś zwolniony z pracy z (trudnymi do zrozumienia) plikami Olson.

Jednak PHP nie jest aktualizowany tak często, jak Olson DB, więc samo użycie konwersji stref czasowych PHPs może pozostawić nieaktualne informacje DST i wpłynąć na poprawność danych. Chociaż nie należy się tego często zdarzać, może się zdarzyć i stanie się tak, jeśli będziesz mieć dużą bazę użytkowników na całym świecie.

Aby poradzić sobie z powyższym problemem, użyj pakietu pecl timezonedb . Jego funkcją jest aktualizacja danych strefy czasowej PHP. Zainstaluj ten pakiet tak często, jak jest aktualizowany. (Nie jestem pewien, czy aktualizacje tego pakietu dokładnie odpowiadają aktualizacjom Olsona, ale wydaje się, że są aktualizowane z częstotliwością, która jest co najmniej bardzo zbliżona do częstotliwości aktualizacji Olsona.)


18

Jeśli Twój projekt to umożliwia, unikaj lokalnej konwersji czasu razem!

Wiem, że niektórym może to zabrzmieć szalenie, ale myślę o UX: użytkownicy przetwarzają daty zbliżone (dziś, wczoraj, następny poniedziałek) szybciej niż daty bezwzględne (2010.09.17, piątek 17 września) na pierwszy rzut oka. A kiedy myślisz o tym więcej, dokładność stref czasowych (i czasu letniego) jest ważniejsza, im bliżej jest daty now(), więc jeśli możesz wyrażać daty / godziny danych w formacie względnym przez +/- 1 lub 2 tygodnie, reszta daty mogą być w UTC i nie będzie miało to większego znaczenia dla 95% użytkowników.

W ten sposób możesz przechowywać wszystkie daty w UTC i dokonywać względnych porównań w UTC i po prostu pokazywać użytkownikom daty UTC poza progiem względnej daty.

Może to również dotyczyć danych wprowadzanych przez użytkownika (ale ogólnie w bardziej ograniczony sposób). Wybór z menu, które ma tylko {Wczoraj, dziś, jutro, następny poniedziałek, następny czwartek} jest dla użytkownika o wiele prostszy i łatwiejszy niż wybór daty. Selektory dat są jednymi z najbardziej wywołujących ból składników wypełniania formularzy. Oczywiście nie będzie to działać we wszystkich przypadkach, ale widać, że potrzeba tylko trochę sprytnego projektu, aby był bardzo wydajny.


16

Chociaż tego nie próbowałem, podejście do regulacji stref czasowych, które uznałem za przekonujące, byłoby następujące:

  1. Przechowuj wszystko w UTC.

  2. Utwórz tabelę TZOffsetsz trzema kolumnami: RegionClassId, StartDateTime i OffsetMinutes (int, w minutach).

W tabeli przechowywać listę dat i czasów , gdy zmienił czas lokalny, i o ile. Liczba regionów w tabeli i liczba dat zależą od zakresu dat i obszarów świata, które należy obsługiwać. Pomyśl o tym jak o „historycznej” dacie, mimo że daty powinny obejmować przyszłość do pewnego praktycznego limitu.

Jeśli musisz obliczyć czas lokalny dowolnego czasu UTC, po prostu wykonaj następujące czynności:

SELECT DATEADD('m', SUM(OffsetMinutes), @inputdatetime) AS LocalDateTime
FROM   TZOffsets
WHERE  StartDateTime <= @inputdatetime
       AND RegionClassId = @RegionClassId;

Możesz buforować tę tabelę w pamięci podręcznej w swojej aplikacji i używać LINQ lub innych podobnych metod do wykonywania zapytań, a nie do bazy danych.

Dane te mogą być destylowane z bazy danych tz domeny publicznej .

Zalety i przypisy tego podejścia:

  1. Żadne reguły nie są zapisywane w kodzie, można łatwo dostosować przesunięcia dla nowych regionów lub zakresów dat.
  2. Nie musisz obsługiwać wszystkich zakresów dat ani regionów, możesz je dodać w razie potrzeby.
  3. Regiony nie muszą bezpośrednio odpowiadać granicom geopolitycznym i aby uniknąć powielania wierszy (na przykład większość stanów w USA obsługuje DST w ten sam sposób), możesz mieć szerokie wpisy RegionClass, które łączą się w innej tabeli z bardziej tradycyjnymi listami stany, kraje itp.
  4. W sytuacjach takich jak USA, w których data rozpoczęcia i zakończenia DST zmieniła się w ciągu ostatnich kilku lat, jest to dość łatwe do rozwiązania.
  5. Ponieważ w polu StartDateTime można również zapisać czas, standardowy czas przełączania 2:00 AM jest obsługiwany z łatwością.
  6. Nie wszędzie na świecie stosuje się 1-godzinny czas letni. To z łatwością radzi sobie z tymi przypadkami.
  7. Tabela danych jest wieloplatformowa i może być osobnym projektem typu open source, z którego mogą korzystać programiści korzystający z niemal dowolnej platformy baz danych lub języka programowania.
  8. Można tego użyć w przypadku przesunięć, które nie mają nic wspólnego ze strefami czasowymi. Na przykład 1-sekundowe korekty, które pojawiają się od czasu do czasu w celu dostosowania do rotacji Ziemi, historyczne korekty kalendarza gregoriańskiego i wewnątrz niego itp.
  9. Ponieważ znajduje się w tabeli bazy danych, standardowe zapytania raportów itp. Mogą wykorzystać dane bez konieczności przeszukiwania kodu logiki biznesowej.
  10. To obsługuje również przesunięcia stref czasowych, jeśli chcesz, i może nawet uwzględniać specjalne historyczne przypadki, w których region jest przypisany do innej strefy czasowej. Wszystko czego potrzebujesz to początkowa data, która przypisuje przesunięcie strefy czasowej do każdego regionu z minimalną datą początkową. Wymagałoby to utworzenia co najmniej jednego regionu dla każdej strefy czasowej, ale pozwoliłoby zadać ciekawe pytania, takie jak: „Jaka jest różnica w czasie lokalnym między Yuma, Arizona i Seattle, Waszyngton, 2 lutego 1989 r. O 5:00 rano?” (Wystarczy odjąć jedną SUMĘ () od drugiej).

Teraz jedyną wadą tego podejścia lub innych jest to, że konwersje z lokalnego czasu GMT nie są idealne, ponieważ każda zmiana DST, który ma negatywny przesunięcie zegara powtarza dany czas lokalny. Obawiam się, że nie ma łatwego sposobu na poradzenie sobie z tym. Jednym z powodów, dla których przechowywanie lokalnych czasów są złe wieści.


8
Twój pomysł na bazę danych został już zaimplementowany jako Baza danych Olson. Podczas gdy czas letni powoduje nakładanie się, określając strefę czasową w świetle dziennym może pomóc rozwiązać problem. 2:15 EST i 2:15 EDT to różne czasy. Jak zauważono w innych postach, określenie przesunięcia również rozwiązuje niejednoznaczność.
BillThor,

5
Dużym problemem związanym z utrzymywaniem własnej bazy danych jest jej aktualizacja. Serwis Olson i Windows są obsługiwane dla Ciebie. Miałem więcej niż jeden przypadek złych przejść DST, ponieważ tabele były nieaktualne. Całkowite ich usunięcie i poleganie na bazie danych na poziomie systemu operacyjnego lub systemu operacyjnego jest znacznie bardziej niezawodne.
Matt Johnson-Pint

4
Nie twórz własnej bazy danych : zawsze polegaj na API systemu!
Alex

15

Niedawno miałem problem z aplikacją internetową, w której na post-backie Ajaxa data i godzina powrotu do mojego kodu po stronie serwera była inna niż data i godzina.

Najprawdopodobniej miało to związek z moim kodem JavaScript na kliencie, który utworzył datę wysłania z powrotem do klienta jako ciąg, ponieważ JavaScript dostosowywał się do strefy czasowej i czasu letniego, aw niektórych przeglądarkach obliczenia, kiedy zastosować czas letni wydawało się być inne niż w innych.

Ostatecznie zdecydowałem się całkowicie usunąć obliczenia daty i godziny na kliencie i wysłałem z powrotem na mój serwer na klucz liczb całkowitych, który następnie został przetłumaczony na serwerze data i godzina, aby umożliwić spójne transformacje.

Moje wnioski z tego: nie używaj obliczeń daty i godziny JavaScript w aplikacjach internetowych, chyba że absolutnie musisz.


JavaScript działa na komputerze klienta, a nie na serwerze. Podstawową datetime Javascript jest datą klienta, a nie datą serwera.
BalusC

Cześć Balus C. Rozumiem to (z mojego oryginalnego postu: „skrypt javacode na kliencie, który zbudował datę ...”). Mój problem polegał na tym, że niektóre maszyny klienckie przetwarzały DST w jeden sposób, a inne w inny sposób. Dlatego przeniosłem cały proces przetwarzania na serwer, aby zapobiec dziwności przeglądarki
Joon

@ Joon - w implementacjach javascript występują błędy, których nie można wykryć lub na które nie można pozwolić. Więc tak, nigdy nie używaj obliczeń daty ECMAScript po stronie klienta dla rzeczy, które mają znaczenie (choć w innym przypadku możesz zrobić całkiem dobrą robotę).
RobG

14

Uderzyłem w dwa rodzaje systemów: „systemy planowania zmian (np. Pracownicy fabryki)” i „systemy zarządzania zależne od gazu)…

23 i 25 godzinne dni są bólem, z którym trzeba sobie poradzić, podobnie jak 8-godzinne zmiany, które trwają 7 lub 9 godzin. Problem polega na tym, że każdy klient, a nawet dział klienta, ma inne reguły, które stworzyli (często bez dokumentacji) na temat tego, co robią w tych szczególnych przypadkach.

Niektórych pytań najlepiej nie zadawać klientowi, dopóki nie zapłacą za „gotowe oprogramowanie”. Bardzo rzadko zdarza się znaleźć klienta, który myśli o tego rodzaju problemach przy zakupie oprogramowania.

Myślę, że we wszystkich przypadkach należy zapisać czas w UTC i przeliczyć na czas lokalny / z czasu lokalnego przed zapisaniem daty / godziny. Jednak nawet wiedzieć, który czas zajmuje dany czas, może być trudny dzięki czasom letnim i strefom czasowym.


6
Moja dziewczyna, pielęgniarka, pracuje nocami i muszą wpisać strefę czasową podczas przejścia na czas letni. Na przykład 2AM CST kontra 2AM CDT
Joe Phillips

1
Tak, jest to powszechne: obliczając średnią (cywilną) dzienną, musisz poradzić sobie z dniami 23, 24 lub 25 godzin. W rezultacie, kiedy obliczasz, dodaj 1 dzień, nie dodasz 24 godzin ! Po drugie, nie próbuj budować własnego kodu strefy czasowej; używaj tylko API systemu. I nie zapomnij zaktualizować każdego wdrożonego systemu, aby uzyskać aktualną bazę danych stref czasowych .
Alex

12

W sieci reguły nie są tak skomplikowane ...

  • Po stronie serwera użyj UTC
  • Po stronie klienta użyj Olson
    • Powód: Przesunięcia UTC nie są bezpieczne dla światła dziennego (np. Nowy Jork to EST (UTC - 5 godzin) przez cały rok, EDT (UTC - 4 godziny) przez resztę roku).
    • Do określenia strefy czasowej po stronie klienta masz dwie opcje:

Reszta to po prostu konwersja UTC / lokalna przy użyciu bibliotek datetime po stronie serwera. Dobrze iść...


2
Jest to dobra rada jako punkt wyjścia, ale całkowicie zależy od zastosowania. Może to być w porządku w przypadku przyjaznej witryny, ale jeśli aplikacja ma jakiś aspekt prawny / jurysdykcyjny / finansowy, nad którym ktoś może pozwać (pracowałem nad kilkoma), jest to nadmierne uproszczenie, ponieważ istnieją różne rodzaje „ czas ”, jak wspomniano w innym miejscu na tej stronie.
DavidWalley,

12

Jeśli chodzi o aplikacje działające na serwerze , w tym strony internetowe i inne usługi zaplecza, ustawienie strefy czasowej serwera powinno zostać zignorowane przez aplikację.

Częstą wskazówką jest ustawienie strefy czasowej serwera na UTC. Jest to rzeczywiście dobra najlepsza praktyka, ale jest pomocna w przypadku aplikacji, które nie są zgodne z innymi najlepszymi praktykami. Na przykład usługa może zapisywać pliki dziennika z lokalnymi znacznikami czasu zamiast znaczników czasu opartych na UTC, tworząc w ten sposób niejednoznaczności podczas przejścia wstecznego na czas letni. Ustawienie strefy czasowej serwera na UTC naprawi aplikację. Jednak prawdziwą poprawką byłoby rejestrowanie przez aplikację przy użyciu UTC.

Kod po stronie serwera, w tym strony internetowe, nigdy nie powinien oczekiwać, że lokalna strefa czasowa serwera będzie czymś szczególnym.

W niektórych językach lokalna strefa czasowa może łatwo wkradać się do kodu aplikacji. Na przykład DateTime.ToUniversalTimemetoda w .NET zostanie przekonwertowana z lokalnej strefy czasowej na UTC, a DateTime.Nowwłaściwość zwróci bieżący czas w lokalnej strefie czasowej. Ponadto Datekonstruktor w JavaScript korzysta z lokalnej strefy czasowej komputera. Istnieje wiele innych takich przykładów. Ważne jest, aby ćwiczyć programowanie obronne, unikając kodu używającego ustawień lokalnej strefy czasowej komputera.

Zarezerwuj, używając lokalnej strefy czasowej dla kodu po stronie klienta, takiego jak aplikacje komputerowe, aplikacje mobilne i JavaScript po stronie klienta.


11

Ustaw swoje serwery na UTC i upewnij się, że wszystkie są skonfigurowane dla ntp lub równoważnego.

UTC pozwala uniknąć problemów związanych z czasem letnim, a niezsynchronizowane serwery mogą powodować nieprzewidywalne wyniki, których diagnozowanie zajmuje trochę czasu.


9

Zachowaj ostrożność podczas obchodzenia się ze znacznikami czasu przechowywanymi w systemie plików FAT32 - zawsze jest on utrzymywany we współrzędnych czasu lokalnego (które obejmują czas letni - patrz artykuł msdn ). Spaliłem się na tym.


Świetny punkt NTFS nie ma tego problemu, ale niektóre osoby nadal używają FAT32 - szczególnie na kluczach USB.
Matt Johnson-Pint

7

Jeszcze jedno, upewnij się, że serwery mają zastosowaną aktualną łatkę na światło dzienne.

W ubiegłym roku mieliśmy sytuację, w której nasze czasy były konsekwentnie o jedną godzinę przez trzy tygodnie dla użytkowników z Ameryki Północnej, mimo że korzystaliśmy z systemu opartego na UTC.

Okazuje się, że w końcu były to serwery. Potrzebowali tylko zaktualizowanej poprawki ( Windows Server 2003 ).


6

DateTimeZone::listAbbreviations()Wyjście PHP

Ta metoda PHP zwraca tablicę asocjacyjną zawierającą niektóre „główne” strefy czasowe (jak CEST), które same w sobie zawierają bardziej szczegółowe „geograficzne” strefy czasowe (jak Europa / Amsterdam).

Jeśli używasz tych stref czasowych i ich informacji o przesunięciu / czasie letnim, niezwykle ważne jest, aby pamiętać o następujących kwestiach:

Wygląda na to, że uwzględniono wszystkie różne konfiguracje przesunięcia / czasu letniego (w tym konfiguracje historyczne) każdej strefy czasowej!

Na przykład Europa / Amsterdam można znaleźć sześć razy na wyjściu tej funkcji. Dwa wystąpienia (przesunięcie 1172/4772) dotyczą czasu Amsterdamu używanego do 1937 r .; dwa (1200/4800) to czas wykorzystany między 1937 a 1940 rokiem; a dwa (3600/4800) są używane od 1940 r.

Dlatego nie można polegać na informacjach przesunięcia / DST zwróconych przez tę funkcję, ponieważ są one obecnie prawidłowe / są w użyciu!

Jeśli chcesz poznać bieżące przesunięcie / czas letni dla określonej strefy czasowej, musisz zrobić coś takiego:

<?php
$now = new DateTime(null, new DateTimeZone('Europe/Amsterdam'));
echo $now->getOffset();
?>

5

Jeśli zdarzy ci się utrzymywać systemy baz danych działające z aktywnym DST, sprawdź dokładnie, czy należy je zamknąć podczas przejścia jesienią. Mandy DBS (lub inne systemy) nie lubi dwa razy minąć tego samego punktu w czasie (lokalnym), co dokładnie dzieje się po cofnięciu zegara jesienią. SAP rozwiązał to za pomocą (naprawdę schludnego) obejścia - zamiast cofać zegar, po prostu pozwolili wewnętrznemu zegarowi pracować z połową normalnej prędkości przez dwie godziny ...


4

Czy używasz platformy .NET ? Jeśli tak, pozwól, że przedstawię ci typ DateTimeOffset dodany z .NET 3.5.

Ta struktura zawiera zarówno a, jak DateTimei Offset ( TimeSpan), który określa różnicę między DateTimeOffsetdatą i godziną instancji a skoordynowanym czasem uniwersalnym (UTC).

  • Metoda DateTimeOffset.Nowstatyczna zwróci DateTimeOffset instancję składającą się z bieżącego (lokalnego) czasu i lokalnego przesunięcia (zgodnie z definicją w regionalnych informacjach systemu operacyjnego).

  • Metoda DateTimeOffset.UtcNowstatyczna zwróci DateTimeOffsetinstancję składającą się z bieżącego czasu w UTC (tak jakbyś był w Greenwich).

Inne przydatne typy to klasy TimeZone i TimeZoneInfo .


To nie jest rozwiązanie przedstawionego problemu.
caradrye

4

Dla tych, którzy zmagają się z tym w .NET , sprawdź, czy warto skorzystać DateTimeOffseti / lub TimeZoneInfowarto poświęcić chwilę.

Jeśli chcesz korzystać ze stref czasowych IANA / Olson lub uważasz , że wbudowane typy są niewystarczające dla Twoich potrzeb, sprawdź Noda Time , która oferuje znacznie inteligentniejszy interfejs API daty i godziny dla platformy .NET.


4

Reguły biznesowe powinny zawsze działać w czasie cywilnym (chyba że istnieją przepisy prawne, które stanowią inaczej). Pamiętaj, że czas cywilny to bałagan, ale ludzie go używają, więc to jest ważne.

Wewnętrznie przechowuj znaczniki czasu w czymś takim, jak czas cywilny w sekundach od epoki. Epoka nie ma znaczenia, szczególnie (I sprzyjać epoki Uniksa ), ale robi to łatwiejsze niż alternatywa. Udawaj, że sekundy przestępne nie istnieją, chyba że robisz coś, co naprawdę ich potrzebuje (np. Śledzenie satelitarne). Odwzorowanie między znacznikami czasu i wyświetlanym czasem jest jedynym punktem, w którym należy zastosować reguły DST ; zasady zmieniają się często (na poziomie globalnym, kilka razy w roku; obwiniaj polityków), więc powinieneś upewnić się, że nie kodujesz na stałe mapowania. Baza danych TZ Olsona jest nieoceniona.


3
Problem polega na tym, że czas cywilny (inaczej kalendarzowy) nie reprezentuje właściwie ani jednej chwili w czasie. Jeśli przyjmiesz podejście sekund po epoce, czy naprawdę będziesz rozliczał się z każdą chwilą, która została pominięta lub przewinięta w przypadku zmian czasu letniego? Prawdopodobnie nie. Podstawa epoki działa tylko w stosunku do UTC lub jakiegoś innego stałego, chwilowego odniesienia.
Matt Johnson-Pint

@MattJohnson Stąd część „reguł biznesowych”. Jeśli przepisy mówią, że coś dzieje się o 2:30 rano (lub w dowolnym innym czasie), nastąpi to dwa razy w ciągu jednego dnia w roku i nigdy w ciągu jednego dnia w roku. Tego oczekuje klient, jeśli nie wyjaśni zasady.
user253751 16.07.16

Utrzymywanie wewnętrznych znaczników czasu w czasie cywilnym może być bardzo trudne. Utrzymywanie go w sekundach od czasu, gdy epoka jest jeszcze trudniejsza, powiedziałbym wręcz niebezpiecznie. Jestem pewien, że są ludzie, którzy to robią i może być możliwe, aby działał prawidłowo przez większość czasu, jeśli jesteś bardzo ostrożny, ale nie można tego uznać za najlepszą praktykę lub ogólne zalecenie.
Steve Summit

2

Chciałem tylko wskazać dwie rzeczy, które wydają się niedokładne lub przynajmniej mylące:

Zawsze utrzymuj czas zgodnie ze zunifikowanym standardem, na który nie mają wpływu oszczędności czasu. GMT i UTC były wymieniane przez różne osoby, choć wydaje się, że najczęściej wymieniane są UTC.

Dla (prawie) wszystkich praktycznych celów obliczeniowych UTC to tak naprawdę GMT. O ile nie widzisz znaczników czasu z ułamkiem sekundy, masz do czynienia z GMT, co czyni to rozróżnienie zbędnym.

Uwzględnij lokalne przesunięcie czasu bez zmian (w tym przesunięcie czasu letniego) podczas przechowywania znaczników czasu.

Znacznik czasu jest zawsze reprezentowany w GMT, a zatem nie ma przesunięcia.


1
Lokalne przesunięcie czasu pozwoli odtworzyć oryginalny „czas na ścianie” zdarzenia. Jeśli nie przechowujesz tego dodatkowego pola, dane zostaną utracone.
nogridbag

Tak, z wyjątkiem tego, że przesunięcia UTC i GMT są odwrotne. Na przykład UTC-0700 jest taki sam jak GMT + 0700. Naprawdę, wszystko, co cyfrowe powinno obecnie korzystać z UTC.
Matt Johnson-Pint,

1
@Matt: czy jesteś pewien, że przesunięcia UTC i GMT są odwrotne? gdzie mogę o tym przeczytać?
Reto Höhener,

Właściwie myślę, że wcześniej się myliłem. GMT i UTC nie są odwrócone. Chodzi o to, że istnieją implementacje, które pokazują je odwrotnie, takie jak baza danych IANA / Olson / TZDB. Zobacz tutaj . Innym obszarem, w którym widać odwrotne przesunięcia, jest funkcja getTimezoneOffset () javascript.
Matt Johnson-Pint,

@MattJohnson: To są hacki i powinny zostać zniesione.
Alix Axel

2

Oto moje doświadczenie: -

(Nie wymaga żadnej biblioteki innej firmy)

  • Po stronie serwera przechowuj czasy w formacie UTC, aby wszystkie wartości daty / godziny w bazie danych były w jednym standardzie, niezależnie od lokalizacji użytkowników, serwerów, stref czasowych lub czasu letniego.
  • Na warstwie interfejsu użytkownika lub w wiadomościach e-mail wysyłanych do użytkownika należy wyświetlać czasy według użytkowników. W tym celu należy przesunąć strefę czasową użytkownika, aby dodać to przesunięcie do wartości UTC bazy danych, co spowoduje czas lokalny użytkownika. Możesz albo przesunąć strefę czasową użytkownika podczas rejestracji, albo możesz automatycznie wykryć go na platformach internetowych i mobilnych. W przypadku stron internetowych funkcja JavaScript getTimezoneOffset () jest standardem od wersji 1.0 i jest kompatybilna ze wszystkimi przeglądarkami. (Patrz: http://www.w3schools.com/jsref/jsref_getTimezoneOffset.asp )

To nie działa, jeśli weźmiesz pod uwagę zmiany czasu letniego. getTimezoneOffsetzwraca przesunięcie dla daty i godziny wywołania. To przesunięcie może się zmieniać, gdy strefa czasowa zmienia się w czasie letnim lub poza nim. Zobacz „strefa czasowa! = Przesunięcie” na wiki tagu strefy czasowej .
Matt Johnson-Pint

1
Jeśli chcesz zapisać alarm typu „zrób coś o 10:00”, nie możesz go zapisać w UTC, ze względu na zmiany czasu letniego. Musisz go zapisać w stosunku do czasu lokalnego.
Alex

2

Film Toma Scotta o strefach czasowych na YouTube na kanale Computerphile zawiera również przyjemny i zabawny opis tego tematu. Przykłady obejmują:

  • Samoa (wyspa na Oceanie Spokojnym) przesuwa strefę czasową o 24 godziny do przodu, aby ułatwić handel z Australią i Nową Zelandią,
  • Bank Zachodni , gdzie 2 populacje ludzi podążają za różnymi strefami czasowymi,
  • XVIII-wieczne zmiany z kalendarza juliańskiego na kalendarz gregoriański (co miało miejsce w XX wieku w Rosji).

1

W rzeczywistości plik kernel32.dll nie eksportuje SystemTimeToTzSpecificLocation. Eksportuje jednak następujące dwa: SystemTimeToTzSpecificLocalTime i TzSpecificLocalTimeToSystemTime ...


1

Nigdy nie polegaj tylko na takich konstruktorach jak

 new DateTime(int year, int month, int day, int hour, int minute, TimeZone timezone)

Mogą zgłaszać wyjątki, gdy określona data nie istnieje z powodu czasu letniego. Zamiast tego zbuduj własne metody tworzenia takich dat. W nich wychwytuj wszelkie wyjątki występujące z powodu czasu letniego i dostosuj potrzebny czas z przesunięciem przejścia. Czas letni może wystąpić w różnych terminach i o różnych godzinach (nawet o północy w Brazylii) zgodnie ze strefą czasową.


1

Tylko jeden przykład, aby udowodnić, że poradzenie sobie z czasem to opisany ogromny bałagan i że nigdy nie możesz być samozadowolony. W kilku miejscach na tej stronie sekundy przestępne zostały zignorowane.

Kilka lat temu system operacyjny Android użył satelitów GPS, aby uzyskać odniesienie do czasu UTC, ale zignorował fakt, że satelity GPS nie wykorzystują sekund przestępnych. Nikt nie zauważył, dopóki w sylwestra nie doszło do zamieszania, gdy użytkownicy telefonów Apple i Android wykonali odliczanie w odstępie około 15 sekund.

Myślę, że od tego czasu zostało to naprawione, ale nigdy nie wiadomo, kiedy te „drobne szczegóły” powrócą, by cię prześladować.


1
  • Nigdy, nigdy nie przechowuj czasu lokalnego bez przesunięcia UTC (lub odniesienia do strefy czasowej) - przykłady tego, jak tego nie robić, obejmują FAT32 i struct tm w C.¹
  • Zrozum, że strefa czasowa jest kombinacją
    • zestaw przesunięć UTC (np. +0100 zimą, +0200 latem)
    • zasady określające, kiedy nastąpi przełączenie (które może się zmieniać w czasie: na przykład w latach 90. UE zharmonizowała przejście na ostatnie niedziele w marcu i październiku o godzinie 02:00 czasu standardowego / 03:00 czasu letniego; wcześniej było inaczej między państwami członkowskimi).

¹ Niektóre implementacje struct tmprzechowują przesunięcie UTC, ale nie stało się to standardem.


-4

W przypadku baz danych (w szczególności MySQL , ale dotyczy to większości baz danych), trudno mi było przechowywać UTC.

  • Bazy danych zwykle domyślnie działają z datetime serwera (to znaczy CURRENT_TIMESTAMP).
  • Zmiana strefy czasowej serwera może być niemożliwa.
  • Nawet jeśli możesz zmienić strefę czasową, możesz mieć kod innej firmy, który oczekuje, że strefa czasowa serwera będzie lokalna.

Odkryłem, że łatwiej jest po prostu przechowywać datę i godzinę serwera w bazie danych, a następnie pozwolić bazie danych przekonwertować przechowywaną datę i godzinę z powrotem na UTC (czyli UNIX_TIMESTAMP ()) w instrukcjach SQL. Następnie możesz użyć datetime jako UTC w kodzie.

Jeśli masz 100% kontroli nad serwerem i całym kodem, prawdopodobnie lepiej jest zmienić strefę czasową serwera na UTC.


Czas lokalny (czas serwera) może być niejednoznaczny podczas przejściowych zmian czasu letniego. Nie jest niezawodne w użyciu zgodnie z opisem. Czas lokalny serwera może wskazywać więcej niż jeden czas UTC.
Matt Johnson-Pint

Czas lokalny jest w porządku, jeśli serwer znajduje się w rozsądnej strefie czasowej, tzn. Takiej, która nie wykonuje czasu letniego.
sayap
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.