Wpis z mikrobloga

Dam wam protipa (w sumie dość oczywistego, ale jakoś o tym nie piszą, a powinni!). Jak robicie apkę, która gdzieś tam w logice korzysta z czasu, to domyślnie używajcie czasu UTC. Nie ma co się #!$%@?ć z lokalnym czasem.
Dlaczego?
- Do UTC są domyślne metody, a jak lubicie funkcyjnie, to date-fns robi robotę i jest leciutki.
- Większość bazodanowych ORM domyślnie w dialekcie konwertuje do UTC. Nie trzeba dodawać customowych configów, by temu zapobiec (i dobrze, bo nie powinno się tego zmieniać).
- Przy czasie lokalnym, gdy zmienicie lokalizację serwera bez przestawienia timezone na serwerze, z tych samych danych, mogą powstawać inne wyniki. Niby można czas na serwerze przestawić, a jak niemożna, to apkę wirtualizować, ale po co dodawać roboty? Użyj UTC!
- Bez UTC, jak masz międzynarodowy team, to po jednej stronie wody testy przechodzą, a po drugiej nie.
- Konwersja z UTC, do dowolnego czasu lokalnego jest banalnie prosta, zazwyczaj nawet nie musisz się tym przejmować.


Jak sobie poradzić, gdy już masz czas lokalny? Wirtualizacja, ewentualnie moment.js.
Bo chyba nie będziesz wszystkiego przepisywać na UTC, prawda? ( ͡° ͜ʖ ͡°)

TL;DR


#javascript #nodejs #naukaprogramowania #programowanie i jeszcze #protip
  • 17
Jak robicie apkę, która gdzieś tam w logice korzysta z czasu, to domyślnie używajcie czasu UTC.


@niepodszywamsiepodbiauka: niby tak, ale nie do końca. Wyobraźmy sobie, że robisz kalendarz i do kalendarza sobie wpisujesz, że będzie spotkanie 24 lutego 2022 roku o 15:00 (np. w Krakowie). Wszystko spoko, zapisujemy sobie datę 24 lutego 2022 roku o 14:00 UTC (czyli 15:00 CET). Następnie wchodzi plan, by zrezygnować ze zmiany czasu na letni w
@Hauleth: Nie jesteś wstanie przewidzieć zmian prawnych. To jak w Japonii, umiera cesarz i trzeba tworzyć kalendarz na nowo. :P
@alex-fortune: Timestampy mają swoje wady. Zresztą, ta nazwa mówi sama przez się. Trudno się na nich operuje, nie posiadają paru haków (leap second), w logice zamiast nazw, zaczynasz używać magic numbers albo definiujesz całą stertę dziwnych stałych, a z samej liczby nie jesteś wstanie powiedzieć na jakiej dacie konkretnie jesteś
@niepodszywamsiepodbiauka: Trudno? To są integery - wystarczy mieć opakowane to w typ ( Boxing w obiekt tudzież typedef ) i jest okej. Leap second nie jest kwestią którą timestamp powinien się zajmować, bo jest to związane z kalkulacją dnia, a nie mierzeniem czasu. Co do logiki - jw, boxing/typedef rozwiązuje sprawę, a to, że z samej liczby nie jesteś w stanie powiedzieć to żaden problem bo nie po to trzymasz dane
Nie jesteś wstanie ifować zmian prawnych


@niepodszywamsiepodbiauka: tak, dla tego w podanym przeze mnie przypadku zapisujesz datę bez strefy czasowej "tak jak jest" bez zabawy z zamianą na UTC czy w drugą stronę.

Dam Ci inna poradę, sto razy lepszą - używaj timestampów


@alex-fortune: heh, oprócz tego co powiedziała @niepodszywamsiepodbiauka (leap seconds) to jeszcze jest sporo rzeczy, których timestampy zwyczajnie nie potrafią ogarnąć same z siebie (lub działają "wolniej" jeśli
@Hauleth: już teraz są 64 bitowe timestampy :) poza tym dochodzi kwestia tego, że nie wszędzie na świecie tak samo trzyma się datę, a co za tym idzie formatowanie do jakiegokolwiek stringa i operowanie na nim to imo głupota.
@alex-fortune: dla tego czas trzymasz (o ile możesz) w postaci struktury z polami:

- dzień
- miesiąc
- rok
- godzina
- minuta
- sekunda
- nanosekunda

Dodatkowo dodajesz strefę czasową jeśli składujesz czas ze strefą.
@niepodszywamsiepodbiauka: @Hauleth: @alex-fortune: Orientujecie się może, czy timestampy początku i końca danego miesiąca lub dnia będą takie same niezależnie od lokalnego czasu?

Na serwerze Node.js używam moment-timezone:

const getMonthTimestamp = () =>
moment()
.tz('Europe/Warsaw')
.date(1)
.hour(0)
.minute(0)
.seconds(0)
.unix()

W przeglądarce:

const getMonthTimestamp = () =>
+new Date((new Date).getFullYear(), (new Date).getMonth()) / 1000

Nie jestem pewien, czy jeśli bym zrezygnował z moment-timezone i używał tej drugiej funkcji na serwerze,
@Verijon: timestamp to timestamp, nie reprezentuje momentu w żadnym miejscu na ziemi, tylko określa punkt w czasie. To oznacza, że kiedy konwertujesz konkretną datę na timestamp, to w zalezności od timezone w którym jesteś dostaniesz różny timestamp ( bo 19:00 27 Czerwca w Polsce to inny punkt w czasie niż 19:00 27 Czerwca w Tokio )
@Hauleth: @alex-fortune: Dzięki, miałem mindfucka.
Poczytałem trochę i doszedłem do wniosku, że w moim przypadku najlepiej będzie zamiast timestampów zapisywać w bazie UTC z zerowym offsetem.
Powyższa funkcja wyglądałaby tak:

new Date((new Date).getUTCFullYear(), (new Date).getUTCMonth()).toISOString()
i zwraca

2019-05-31T22:00:00.000Z
w sumie nikt mnie nie poprawił, ale w powyższym kodzie zamiast

new Date((new Date).getUTCFullYear(), (new Date).getUTCMonth()).toISOString()

powinno być

new Date((new Date).getFullYear(), (new Date).getMonth()).toISOString()

bo działamy na czasie lokalnym i później konwertujemy na UTC z zerowym offsetem