Zakończyłem z sukcesem walkę z timestampami w MySQL-u. Po czterech dniach wysiłków z doskoku odkryłem prawdę, która nie była schowana jak klucz pod wycieraczką (dygresja dalej) ale błyszczała jak nowa moneta na wierzchu. Ciekawe, że biorąc się za bary z problemem, w pierwszej chwili, chyba intuicyjnie, złapałem go od dobrej strony ale potem popadłem w wielką konfuzję i stworzyłem w głowie chaos.
Jakiś anglosaski koder, spec od Javascriptu, PHP i MySQL-a napisał gdzieś, że ludzie gdy w grę wchodzi programowanie, zdecydowanie (definitely) mają problem z czasem. Potwierdzam. Największy kłopot sprawiał mi brak punktu odniesienia, w tym znaczeniu, że pomimo istnienia czasu Greenwich, czas wciąż płynie, nawet w trakcie robienia testów, więc przy ich analizie trzeba wciąż brać to pod uwagę.
Nie pomagała wizualizacja kuli ziemskiej obracającej się wokół własnej osi, oświetlanej przez Słońce to tu to tam. Z powodu niedoczytania dokumentacji popadłem w szalony stan w którym zaczynałem wątpić czy istnieje GMT!
Dwie rzeczy okazały się szalupami ratunkowymi w oceanie czasu i naprowadziły mnie na rozwiązanie: użycie testów w jak największym stopniu niezależnych od upływu czasu oraz podejście od ogółu do szczegółu, krok po kroku. Przy testowaniu najpierw oparłem się na ID-kach rekordów, tak by mieć pewność, że są takie same niezależnie od strefy czasowej, dopiero gdy uzyskałem pewność zająłem się konwersją dat.
A taka konwersja wygląda tak:
jakiś klient z Antarktydy, ze stacji McMurdo (GMT + 12:00) zagląda na naszą stronę na której ma zobaczyć informacje czasowe pobrane z MySQL-a ale z czasami skonwertowanymi na NZST czyli czas Antarktydy.
Sprawdzam Javascriptem, która u polarnika jest godzina i jakie ma przesunięcie względem GMT, a potem przesyłam te dane do samego MySQL-a (z towarzyszeniem, np. PHP):
var now = new Date();
var tzo = now.getTimezoneOffset();
var tstamp = parseInt(now.getTime()/1000);
W MySQL-u konwertujemy uzyskany czas w następujący sposób:
SELECT CONVERT_TZ(FROM_UNIXTIME(tstamp),'+02:00','+12:00');
FROM_UNIXTIME() zamienia nam timestamp na czas w formacie czytelnym dla człowieka, np.:
SELECT FROM_UNIXTIME(1157464260);
da nam:
2006-09-05 15:51:00
Funkcja CONVERT_TZ() ma trzy argumenty: czas w postaci jak pokazałem wyżej, strefa czasowa z której konwertujemy oraz strefa wynikowa. Kluczowy jest argument drugi, który w praktyce jest strefą czasową serwera MySQL. Wg. dokumentacji powinna to być strefa czasowa połączenia z bazą ale nie miałem okazji tego przetestować, gdyż wszystkie zapytania do MySQL-a pochodzą ze skryptów PHP z tego samego serwera co baza danych.
W moim przypadku serwer jest w strefie CEST (GMT + 02:00) więc taką wartość musiałem podać jako drugi argument. Ostatni argument to przesunięcie względem GMT strefy kolesia z Antarktydy.
Finito! Koniec pieśni! Aż wstyd przyznać, że aż tyle nad tym myślałem.
W trakcie całej tej walki uświadomiłem sobie, że:
- kodowanie z Dziedzicem u boku jest ciężkie, cierpią na tym obie strony,
- mam już blokady mózgowe, które nie pozwalają mi rozwalić błahego problemu, z którym szybko poradziłoby sobie dziecko,
- należy co jakiś czas puścić umysł na wolne obroty, bo ciągłe skupienie na problemie (nawet podczas snu) nie pomaga go rozwiązać (hint: spacer z Dziedzicem),
- rozgryzanie problemu potrafi iść lepiej bez komputera.
Co do dygresji z kluczem pod wycieraczką to przypomniałem sobie w trakcie pisania, że rodzice czasem zostawiali mi klucz do mieszkania właśnie w ten sposób. Gdy wracałem z podstawówki, unosiłem wycieraczkę i już. W miarę upływu czasu zaczęli zostawiać klucz u sąsiadów. Nie jest to wcale pochwała "starych, dobrych", komunistycznych czasów - po prostu dowód, że niewiele się w domu miało cennych rzeczy. I może, że bardziej się ufało ludziom? W Warszawie byłoby to nie do pomyślenia - zbyt wielu sąsiadów wynajmuje lokale i przestaje mieszkać z dnia na dzień.