Jak mogę obsługiwać strefy czasowe w mojej aplikacji internetowej?

106

Szukam lepszego zrozumienia następującej historii użytkownika:

John pracuje w Sidney. O 9:00 rano rejestruje zdarzenie w aplikacji internetowej działającej na serwerze w Zurychu. Następnego dnia jedzie do Nowego Jorku na nadzwyczajne spotkanie, podczas którego należy omówić to wydarzenie. Podczas spotkania wyszukuje wydarzenie według daty i godziny.

Jak widzę, są tu co najmniej dwa problemy:

  1. Jak zapisać znaczniki czasu w bazie danych
  2. Jak mam je przedstawić w interfejsie użytkownika

Kiedy John przeszuka wydarzenie, będzie wiedział, że stało się to o 9:00, ale co powinien wpisać w przeglądarce internetowej? Nie znajdzie niczego, wprowadzając po prostu „9:00” jako znacznik czasu, ponieważ może to być czas w Zurychu lub Nowym Jorku (ponieważ wydarzenie nie zostało znalezione, aplikacja nie ma możliwości dowiedzenia się, że wydarzyło się to w Sidney, więc nie może automatycznie wybrać właściwej strefy czasowej).

Jaki jest dobry sposób, aby zapytać użytkownika o sygnaturę czasową, która może zawierać strefę czasową?

Druga kwestia dotyczy sposobu wyświetlania wyników. Jeśli zespoły z całego świata muszą omówić wydarzenie (i znaleźć powiązane wydarzenia, pomyśl o ataku crackera, który obejmuje kilka witryn na całym świecie jednocześnie).

Jaki jest dobry przykład wyświetlania sygnatur czasowych, które mogły zostać utworzone w innej strefie czasowej?

Uwaga: Skoncentruj się na użyteczności wymagania. Mogę samodzielnie znaleźć mapowanie bazy danych. Obecnie nie mam pewności co do przepływu pracy. Powinien zadawać / przedstawiać niezbędne informacje w sposób nieinwazyjny / intuicyjny. Jeśli możesz, podaj link do istniejącej aplikacji internetowej, która już to rozwiązuje.

Aaron Digulla
źródło
5
Stack Overflow rozwiązuje ten problem, umieszczając wszystko w UTC. Nie zawsze jest to wygodne, ale zdecydowanie jednoznaczne, nietrudne do wykonania i działa.
Ry-
2
UTC kusi, ale OTOH, SO nigdy nie musi synchronizować wydarzeń w kilku strefach czasowych.
Aaron Digulla
3
Co się stanie, jeśli jeden z zaangażowanych krajów uchwali przepisy zmieniające czas lokalny po zaplanowaniu wydarzenia, ale przed wydarzeniem? Jak system powinien sobie z tym poradzić? en.wikipedia.org/wiki/…
Julius Musseau
1
Ten typ klasycznego pytania o strefę czasową był tak zabijany na śmierć przez dziesięciolecia w Internecie iw druku, że jestem zaskoczony, widząc tak żywy wkład i nagrody w tym pytaniu!
BenSwayne
2
Dodam dodatkowy punkt złożoności, wskazując na to, co oczywiste, a mianowicie, że większość zachodniego świata zmienia strefy czasowe dwa razy w roku („czas letni”) i że zasady, kiedy to się dzieje, nie są ani jednolite w skali globalnej, ani koniecznie banalne, mówiąc algorytmicznie?
pt13d

Odpowiedzi:

99

Kwestia przechowywania znaczników czasu jest prosta: przechowuj je w UTC.

Jeśli chodzi o ich wyświetlanie, warto byłoby wziąć ustawienie strefy czasowej urządzenia i użyć jej jako bieżącej strefy czasowej. To powiedziawszy, obok pola „wprowadzanie czasu” powinno znajdować się menu strefy czasowej, które domyślnie wskazuje bieżącą strefę czasową urządzenia, aby użytkownik mógł ją zmienić w razie potrzeby.

Większość Twoich użytkowników prawdopodobnie nie zmieni stref czasowych zbytnio lub wcale. W większości sytuacja, którą nakreśliłeś, jest rzadka. Wdrażając listę rozwijaną z odpowiednią wartością domyślną, powinieneś być w stanie uprościć wszystko tym, którzy się przemieszczają (ponieważ zazwyczaj lepiej rozumieją strefy czasowe niż osoby niebędące podróżnikami).

W rzeczywistości jeszcze lepiej byłoby zapisać strefę czasową, w której urządzenie było ustawione podczas pierwszego uruchomienia aplikacji, a następnie sprawdzić, czy kiedykolwiek się zmieni. Jeśli to się zmieni, oznacza to, że użytkownik jest prawdopodobnie podróżnikiem i prawdopodobnie skorzystałby na rozwijaniu listy stref czasowych. W przeciwnym razie po prostu nie pokazuj menu i domyślnie ustawisz strefę czasową urządzenia (ponieważ użytkownik nie musi o nich wiedzieć). W obu przypadkach należy mieć ustawienie w aplikacji, które pozwala użytkownikowi ręcznie wyświetlać / ukrywać menu rozwijane strefy czasowej.


Podsumowując powyższe:

  • Przy pierwszym uruchomieniu zapisz strefę czasową, w której jest ustawione urządzenie.
  • Użyj tej strefy czasowej jako domyślnej strefy czasowej. Zawsze zakładaj tę strefę czasową.
  • Jeśli urządzenie zmieni strefy czasowe, dodaj listę rozwijaną, aby wybrać strefę czasową, w której znajduje się wydarzenie, ustawiając domyślnie własną strefę czasową urządzenia.
  • Dodaj opcję ręcznego pokazywania / ukrywania menu tej strefy czasowej.
  • Zawsze przechowuj sygnatury czasowe w UTC.
Niet the Dark Absol
źródło
Co rozumiemy przez „strefę czasową” Wydaje się, że jest używany niejednoznacznie. To wygląda jak odniesienie: en.wikipedia.org/wiki/Tz_database Z tego, co mogę powiedzieć, że „strefa czasowa” to „Obszar / lokalizacja”, np. „Ameryka / Nowy_Jork”. To wydaje się być geograficzne, co jest świetne, ponieważ na przykład America / Los_Angeles oznacza ZARÓWNO PST, jak i PDT, w zależności od tego, czy świat działa w czasie letnim. A jeśli tak jest, pytanie brzmi, jak wyliczyć dwuletnie zmiany przesunięcia czasu UTC dla stref? Co też nazywamy tymi ocenami, skoro nie są one „strefami” geograficznie właściwymi?
iJames
To świetna odpowiedź. Czy istnieje najlepsza praktyka dotycząca przechowywania informacji o strefie czasowej? Na przykład - który byłby lepszy - „PST” czy „America / Pacific”? W jaki sposób mogę łatwo przekonwertować znacznik czasu w UTC na strefę czasową przechwyconego użytkownika? Wszelkie najlepsze praktyki w tym zakresie będą mile widziane.
Patthebug
27

W naszych aplikacjach zazwyczaj przechowujemy strefę czasową użytkownika, gdy rejestrujemy się po raz pierwszy, jak to często widać na stronach forów, i zawsze wyświetlamy czas ze strefą czasową .

Jeśli chodzi o przechowywanie dat, najlepszym rozwiązaniem jest UTC. Konwertuj na UTC i umieść go w bazie danych. Podczas pobierania po prostu przekonwertuj czas na strefę czasową ustawioną dla użytkownika.

Musiałem rozwiązać podobny przypadek użycia, w którym niestandardowe powiadomienia, takie jak „Szczęśliwego Nowego Roku”, mogły być wysyłane do wszystkich użytkowników aplikacji internetowej. Ponieważ użytkownicy są rozproszeni po całym świecie, musieliśmy wyświetlić powiadomienie zgodnie ze strefą czasową. Przechowywanie sygnatury czasowej w UTC dobrze służyło naszemu celowi, bez problemów.

W Twoim przypadku, jeśli nie przechowujesz gdzieś strefy czasowej użytkownika, nigdy nie będziesz w stanie dokładnie zwrócić wyników wyszukiwania bez pytania użytkownika o wprowadzenie danych, chyba że zaczniesz korzystać z pewnego rodzaju wykrywania lokalizacji, takiego jak gmaps, ale to nie jest t niezawodny. Musisz więc za każdym razem pytać o strefę czasową, aby upewnić się, że użytkownik wie, co wprowadza na stronie.

Jeśli masz informacje o strefie czasowej, cała aplikacja internetowa powinna działać z ustawieniem strefy czasowej. Dlatego gdy użytkownik wyszuka godzinę 9:00, będzie szukał w strefie czasowej Sydney. Z drugiej strony, jeśli utworzy wydarzenie siedząc w Nowym Jorku, utworzy wydarzenie ze strefą czasową Sydney. Rozwiązujemy takie przypadki, zawsze wyświetlając strefę czasową podczas wyświetlania dat.

Mam nadzieję, że to pomoże! :)

Varun Achar
źródło
Myślę, że po dodaniu listy rozwijanej stref czasowych podczas wyszukiwania i tworzenia wydarzeń jest to droga do zrobienia. (kiedy potrzebuję wyszukać wydarzenie stworzone przez kolegę z Nowego Jorku, nie chcę samodzielnie wykonywać matematyki)
RasmusWL
To świetna odpowiedź. Czy istnieje najlepsza praktyka dotycząca przechowywania informacji o strefie czasowej? Na przykład - który byłby lepszy - „PST” czy „America / Pacific”? W jaki sposób mogę łatwo przekonwertować znacznik czasu w UTC na strefę czasową przechwyconego użytkownika? Wszelkie najlepsze praktyki w tym zakresie będą mile widziane.
Patthebug
11
  1. UTC. Nie komplikuj.

  2. Użyj strefy czasowej, która jest najbardziej odpowiednia dla użytkownika.

    Jeśli wiesz, że użytkownik będzie w Sydney lub podróżował do Sydney na to wydarzenie, będzie myślał w tej strefie czasowej podczas organizowania transportu na to wydarzenie. Fakt, że znajdują się obecnie w Nowym Jorku, jest w dużej mierze nieistotny. I oczywiście, jeśli Twoja aplikacja wyświetla daty w różnych strefach czasowych, powinna zawsze pokazywać strefę czasową obok daty, np. 09:00 EST .

    Jeśli nie zaśmieca to zbytnio interfejsu, możesz wyświetlać daty w strefie czasowej wydarzenia i lokalnej strefie czasowej, np. 2012-06-13 09:00 EST (2012-06-12 19:00 EDT) .

    Twierdziłbym, że wyszukiwanie jest podobnym problemem, z jednym zastrzeżeniem: możemy tolerować fałszywe alarmy (uzyskanie wyniku, którego się nie spodziewaliśmy), ale nie możemy znieść fałszywych negatywów (nie otrzymujemy wyniku, którego oczekiwaliśmy).

    Ponownie, skupiłbym się na wyszukiwaniu strefy czasowej najbardziej odpowiedniej dla użytkownika (np. Strefa czasowa wydarzenia) i nadaniu tym wynikom priorytetu w wynikach wyszukiwania, ale możesz również zwrócić zdarzenia pasujące do innych stref czasowych, które są istotne dla użytkownika (np. czas lokalny). Jeśli to zrobisz, powinieneś pokazać datę wydarzenia w pasującej strefie czasowej, zwłaszcza jeśli zaznaczysz pasujący tekst.

Richard Poole
źródło
7

Podaję tutaj sugestie dotyczące najlepszej użyteczności, nie martwiąc się zbytnio o wykonalność wdrożenia.
1. Przy pierwszym wydaniu zapisywania zdarzeń w db każdy zgodziłby się na przechowywanie go w UTC

2. Aby zapewnić użytkownikowi jak najlepsze wrażenia, zapisz historię strefy czasowej użytkownika. Gdybyś mógł zapisać znacznik czasu zmiany strefy czasowej, jeszcze lepiej. Pozwoli nam to dać użytkownikowi swobodę zapytań bez wyraźnego określania strefy czasowej za każdym razem.

Dzięki tym funkcjom zobaczmy, jak zostanie obsłużone zapytanie wyszukiwania o godzinie „9.00” autorstwa Johna:
Dzięki wyżej wymienionym funkcjom, teraz wiem, że Jan był w 2 strefach czasowych do daty (lub uzyskam listę stref czasowych dla wspomnianego okresu). Więc ukryję 9.00 ze strefy czasowej Sydney do UTC, odpalę zapytanie. Konwertuj także 9.00 ze strefy czasowej Nowego Jorku na UTC, uruchom zapytanie. W rezultacie pokażę Johnowi 2 wiersze, pokazując, co zrobił o 9.00 w Sydney io 9.00 w Nowym Jorku. W tym przypadku wiersz New York będzie pusty, ale myślę, że nadal powinien być wyświetlany użytkownikowi, aby poinformować go, że szukaliśmy również tej strefy czasowej.

3. Jak dobrze zapytać użytkownika o sygnaturę czasową, która może zawierać strefę czasową?

Jeśli jego strefa czasowa została niedawno zmieniona, za każdym razem, gdy loguje się do aplikacji, powinno być wysyłane powiadomienie, że Twoja domyślna strefa czasowa zostanie zmieniona na natywną strefę czasową.
Tworząc wydarzenie, powiedzmy, że użytkownik wybiera strefę czasową z rozwijanego menu. Nie obciążajmy użytkownika podaniem opcji wszystkich stref czasowych świata. Pierwszą opcją menu rozwijanego powinna być aktualna strefa czasowa urządzenia użytkownika. po tych strefach czasowych z jego historii stref czasowych, następnie UTC, a następnie pozostałe strefy czasowe, których nigdy nie używał do daty.

Jak wyświetlić wyniki, jeśli zespoły z całego świata muszą omówić wydarzenie:

Chciałbym podzielić ten przypadek użycia na liczbę drużyn 2 lub więcej niż 2.
W przypadku tylko 2 drużyn wolałbym, aby każda drużyna widziała znacznik czasu w swojej lokalnej strefie czasowej i strefie czasowej innego zespołu. (Osobiście wolę rozmawiać w strefie czasowej osoby po drugiej stronie ze względu na jej wygodę podczas planowania spotkania). W przypadku więcej niż 2 drużyn lepiej rozważyć bardziej powszechną strefę czasową, np. UTC. W takim przypadku każdy użytkownik powinien widzieć sygnaturę czasową w 2 strefach czasowych, w czasie UTC i w swojej domyślnej strefie czasowej.

Te sugestie są podawane z zamiarem, aby użytkownik nie musiał wykonywać żadnych obliczeń w swoim czasie lokalnym, ale jednocześnie powinien być w stanie płynnie komunikować się z innymi użytkownikami w preferowanej strefie czasowej.

Pranalee
źródło
2
+1 To bardzo ciekawy pomysł, ponieważ wiem, że użytkownik wszedł na wydarzenie o 9:00 w Sidney, więc gdy ten sam użytkownik szuka czasu (bez wyraźnej strefy czasowej), powinienem założyć, że ma na myśli „gdzie byłem tym razem ”
Aaron Digulla
4

Ok, mam inne podejście niż inni:

Po pierwsze, założyłem kilka rzeczy wcześniej.

Osoba wystawiająca wydarzenie posiada smartfon (jeśli jest to przeglądarka to nie muszę robić takich założeń) z:

  1. GPS

  2. Możliwość HTML5.

  3. Możliwości Javascript

Jak zapisać znaczniki czasu w bazie danych?

Rozwiązanie: Oczywiście UTC nałożyłem procedurę poniżej:

Krok 1. Skorzystaj z funkcji Geolokalizacja użytkownika za pomocą funkcji Geolocation API

    window.onload = getMyLocation;

    function getMyLocation() {
        if (navigator.geolocation) {
            navigator.geolocation.getCurrentPosition(displayLocation);
        } else {
            alert("Oops, no geolocation support");
        }
    }

    function displayLocation(position) {
        var latitude = position.coords.latitude;
        var longitude = position.coords.longitude;
        var div = document.getElementById("location");
        div.innerHTML = "You are at Latitude: " + latitude + ", Longitude: " + longitude;
    }

Krok 2. Podaj (Long, Lat) jako argumenty do niektórych (Lat, Long) interfejsów API TimeZone, takich jak interfejs API Yahoo (użyj flagi R, aby przekonwertować Latitude na strefę czasową), aby uzyskać strefę czasową użytkowników.

=> Strefa czasowa użytkownika jest określana bez udziału użytkownika (używam tego, ponieważ nie można po prostu założyć, że użytkownik zna strefę czasową miejsca, w którym mieszka, znałem swoją strefę czasową dopiero po kilku miesiącach lub coś w tym miejscu: P, całkiem głupi! )

Każda tabela zdarzeń ma Timezone, Eventwięc może również mieć CityName Następnie utworzyć kolejną tabelę bazy danych z klasyfikacją na podstawie CityNames. Więc tutaj użytkownik będzie miał dwie kolumny

|---------------------------------------|
|_____NewYork________|______Sydney______|
|                    |                  |
|Event 1             |  Event 2         |
|____________________|__________________| 

W przypadku interfejsu użytkownika

=> użyj API Kalendarza Google lub niektórych API Kalendarza

Powiązane lektury:

  1. Określ strefę czasową na podstawie szerokości / długości geograficznej bez korzystania z usług internetowych, takich jak Geonames.org

  2. Wyszukiwanie strefy czasowej na podstawie szerokości i długości geograficznej

Wiem, że chodzi tylko o pokazanie pomysłu, jak rozwiązać ten problem. Ale zobacz, jak dokładne i lekkie staje się to dla użytkowników, gdy strefa czasowa jest określana za pomocą interfejsów API urządzeń

Mam nadzieję, że to pomoże!

uday
źródło
4
Łatwo jest znaleźć czyjąś strefę czasową bez geolokalizacji. new Date().getTimezoneOffset()podaje w minutach za UTC.
Ry-
@minitech, to prawda, ale co, jeśli wydarzenie odbywa się w Nowym Jorku i gdzieś na południu, w tej samej strefie czasowej. Używam geolokalizacji, abyś mógł wskazać miasto (nawet dokładne), strefę czasową w jednym ujęciu i oprzeć na niej moją tabelę db. Chcę zminimalizować działania użytkownika za pomocą interfejsu API urządzenia, aby zwiększyć skuteczność aplikacji.
uday
Więc? Czas będzie taki sam w obu miejscach, więc nie ma problemu. -1
Ry-
@minitech, możesz zobaczyć ten link, aby dowiedzieć się, dlaczego zalecam używanie interfejsów API urządzenia niż innych metod. webdirections.org/sotmw2011
uday
2
OK, ale problem nie polega na uzyskaniu miasta użytkownika. Chodzi tylko o uzyskanie strefy czasowej. Korzystanie z interfejsu API geolokalizacji, który nie działa na każdej przeglądarce / komputerze, a następnie przekierowanie do interfejsu API kalendarza, to zły sposób na uzyskanie strefy czasowej użytkownika, gdy jest ona dostępna w jednej linii kodu.
Ry-
2

W tym konkretnym przypadku przechowuję oba lokalny, i UTC. UTC jest nieco głównym i służy do synchronizacji i konwersji czasu do bieżącej strefy czasowej. Lokalny jest używany do wyszukiwania i dodatkowych informacji, takich jak:

Masz spotkanie:

12:00 Monday (UTC)
9:00 Monday (Sydney, creation local time)
11:00 Monday (Zurich, local time)

czy jakoś tak. Innym sposobem jest przechowywanie strefy czasowej utworzenia i konwersja w czasie wykonywania (jest to szczególnie lepsze w przypadku, gdy użytkownik zmieni czas spotkania). W każdym razie głównym powodem jest możliwość przywrócenia pierwotnego czasu utworzenia, aby użytkownik mógł się do niego odwołać.

Petr Abdulin
źródło
2
  1. Jak zapisać znaczniki czasu w bazie danych

Podczas tworzenia wydarzenia zapisywałbym czas UTC i lokalną strefę czasową (aka creation time zone). Użyłbym tego, co zapisałem, aby przekonwertować czas UTC na czas lokalny (aka creation time) i przechowywać go razem z czasem UTC icreation time zone .

UWAGA: Mogę przechowywać czas lokalny od samego początku, ale gdy użytkownik wyszukuje wydarzenie, mam nadzieję, że nastąpi konwersja na czas lokalny. Mam również nadzieję, że serwer może wykryć, w której strefie czasowej znajduje się klient.

  1. Jak mam je przedstawić w interfejsie użytkownika

Gdy użytkownik wyszukuje „9:00”, szukałbym wydarzeń zawierających „9:00” w UTC LUB creation time LUB w czasie lokalnym. W przypadku wyników wyświetliłbym jedną tabelę wyników w creation time(ma to na celu wyświetlanie sygnatur czasowych, które mogły zostać utworzone w innej strefie czasowej, ponieważ zakładamy, że użytkownik szuka czasu, w którym utworzył wydarzenie, gdziekolwiek był). , i wyświetl poniżej drugą tabelę wyników z powiązanymi wynikami, na przykład z nagłówkiem „Nie to, czego szukasz? Zobacz powiązane wyniki” (obejmują one pozostałe wyniki UTC i czasu lokalnego).

Ogólnie rzecz biorąc, chciałbym wyświetlić czas UTC, czas lokalny creation time, i creation time zone(tj. Czas lokalny i strefę czasową wydarzenia, w którym zostało utworzone) posortowane według czasu UTC, aby można było zobaczyć, które zdarzenie jest pierwsze, w przypadku dwóch różnych wydarzenia zaplanowano na 9:00 w dwóch różnych strefach czasowych.


źródło
1
+1 Podoba mi się pomysł, aby pokazać wszystkie wydarzenia we wszystkich strefach czasowych, w których odpowiada czas lokalny; Jestem po prostu niezadowolony z SQL ( BETWEENwarunki 24x ).
Aaron Digulla