
Twój agent AI właśnie zarezerwował konsultację na 15:00. Klient jest w Tokio, terapeuta w Berlinie. Które 15:00 miał na myśli agent?
Jeśli odpowiedź nie wynika natychmiast z danych zwróconych przez API, masz błąd strefy czasowej — taki, który po cichu kosztuje firmy tysiące w niestawiennictwach, zgłoszeniach do supportu i utraconym zaufaniu. A gdy autonomiczne agenty AI obsługują rezerwacje bez ludzkiej kontroli, precyzja stref czasowych to nie miły dodatek. To krytyczna infrastruktura.
Tutaj GraphQL pokazuje swoją siłę. W przeciwieństwie do endpointów REST, które zwracają nieprzejrzyste ciągi znaczników czasu i pozostawiają interpretację stref czasowych po stronie wywołującego, dobrze typizowane API GraphQL może kodować semantykę stref czasowych bezpośrednio w schemacie — dając agentom AI jednoznaczne, maszynowo odczytywalne dane czasowe w każdej odpowiedzi.
W Timerise latami pracowaliśmy nad obsługą stref czasowych, która eliminuje tę całą kategorię błędów — dla ludzkich użytkowników i dla agentów AI. Oto jak działa nasze GraphQL API i co to oznacza dla deweloperów budujących własne frontendy lub podłączających autonomicznych agentów.
Główny problem: Czas lokalny to iluzja (i agenci AI nie mogą zgadywać)
Każdy programista uczy się tego prędzej czy później na własnej skórze: czas lokalny nie istnieje w izolacji. „15:00" nie znaczy nic bez punktu odniesienia w postaci strefy czasowej. Człowiek może wywnioskować właściwą strefę z kontekstu. Agent AI nie może — potrzebuje jawnych, ustrukturyzowanych danych. A obsługa stref czasowych jest znacznie bardziej złożona niż dodawanie lub odejmowanie godzin od UTC.
Weź pod uwagę te komplikacje:
- Zmiana czasu (DST) przesuwa zegary do przodu lub do tyłu, co oznacza, że niektóre godziny lokalne występują dwa razy w roku, a niektóre w ogóle nie istnieją
- Reguły stref IANA się zmieniają — rządy modyfikują zasady DST, czasem z zaledwie kilkutygodniowym wyprzedzeniem
- Offsety UTC nie są statyczne —
Europe/Warsawto+01:00zimą i+02:00latem
Jeśli Twój system rezerwacji przechowuje czasy jako „15:00 CET", już masz problem. CET jest niejednoznaczny — nie mówi, czy obowiązuje czas letni. Dlatego Timerise stosuje zupełnie inne podejście.
Architektura UTC-First w Timerise
Nasze API stosuje ścisły model przechowywania UTC-first. Każdy znacznik czasu w bazie danych jest zapisany jako wartość UTC. Żadnych czasów lokalnych w bazie, żadnej niejednoznaczności, żadnych niespodzianek związanych z DST.
Łączymy to z identyfikatorami stref IANA — standardem branżowym utrzymywanym przez IANA Time Zone Database. Zamiast niejasnych skrótów jak „EST" czy „CET" używamy precyzyjnych identyfikatorów jak America/New_York lub Europe/Warsaw, które kodują pełną historię reguł strefowych danej lokalizacji.
Każdy projekt w Timerise posiada wymagane pole localTimeZone — jedno, programatycznie odpytywalne źródło prawdy, które agenci AI mogą odczytywać:
type Project {
localTimeZone: TimeZone! # np. "Europe/Warsaw"
now: DateTime! # Bieżący czas UTC
nowISO: DateTimeISO! # Bieżący czas w strefie projektu
}To jedno pole steruje generowaniem slotów, formatowaniem wyjścia rezerwacji i wyświetlaniem dla wszystkich usług w danym projekcie. Jedno źródło prawdy, zero zgadywania. Agent AI może odpytać localTimeZone raz i używać go do poprawnej interpretacji każdego znacznika czasu zwracanego przez projekt.
Dwa typy DateTime: Maszynowy i czytelny dla ludzi
API Timerise udostępnia dwa typy skalarne, które rozwiązują problem „które 15:00?". To rozróżnienie czyni API wyjątkowo przyjaznym agentom AI — agent zawsze wie, którego pola użyć do logiki, a którego do wyświetlania:
| Skalar | Format | Przykład | Zastosowanie |
|---|---|---|---|
DateTime | UTC ISO 8601 | 2026-02-16T19:43:29.000Z | Arytmetyka czasowa, przechowywanie, porównania |
DateTimeISO | ISO 8601 z offsetem | 2026-02-16T20:43:29+01:00 | Czytelne wyświetlanie dla ludzi |
DateTime to format przyjazny maszynom. Zawsze kończy się na Z (czas Zulu = UTC). Agenci AI powinni używać tego pola do wszystkich obliczeń czasowych — porównań, sortowania, wykrywania konfliktów i logiki harmonogramowania.
DateTimeISO to format przyjazny użytkownikom. Pokazuje czas lokalny z offsetem UTC, więc użytkownik w Warszawie widzi 20:43:29+01:00 — od razu jasne, bez potrzeby przeliczania w głowie. Gdy agent AI musi prezentować czasy użytkownikom końcowym, DateTimeISO dostarcza gotową do wyświetlenia wartość z prawidłowym lokalnym offsetem.
Każdy slot w systemie udostępnia oba:
type Slot {
dateTimeFrom: DateTime! # "2026-02-16T19:43:29.000Z"
dateTimeFromISO: DateTimeISO! # "2026-02-16T20:43:29+01:00"
dateTimeTo: DateTime!
dateTimeToISO: DateTimeISO!
}Dla deweloperów budujących własne frontendy zasada jest prosta: używaj dateTimeFrom / dateTimeTo do arytmetyki czasowej, a dateTimeFromISO / dateTimeToISO do wyświetlania użytkownikom.
Automatyczne wykrywanie strefy użytkownika w custom frontendach
Kiedy budujesz własną stronę rezerwacyjną na Timerise, Twoi użytkownicy mogą znajdować się w innej strefie czasowej niż usługodawca. Oto jak obsłużyć to elegancko.
Wykrywanie po stronie przeglądarki
Nowoczesne przeglądarki udostępniają strefę czasową użytkownika przez Intl API (Application Programming Interface):
const userTimeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;
// Zwraca identyfikator IANA, np. "America/New_York"To zwraca prawidłowy identyfikator IANA — dokładnie taki format, jakiego oczekuje Timerise. Możesz go przekazać bezpośrednio do API przy tworzeniu rezerwacji:
mutation CreateBooking {
bookingCreate(
serviceId: "srv_12345"
slots: ["slot_abc"]
timeZone: "America/New_York" # z Intl API
) {
bookingId
dateTimeFrom
dateTimeFromISO
}
}Parametr timeZone jest zapisywany w dokumencie rezerwacji. Później, gdy użytkownik przegląda potwierdzenie, pole dateTimeFromISO automatycznie formatuje czas w jego strefie czasowej z prawidłowym offsetem.
Przeliczanie czasów wyświetlania dla użytkowników
Co jeśli Twój frontend musi pokazywać czasy slotów w lokalnej strefie użytkownika, a nie usługodawcy? API zwraca zarówno UTC, jak i czas lokalny dostawcy, dając pełną elastyczność.
Opcja A — Pozwól API pracować. Pobierz sloty normalnie i użyj pól DateTime (UTC). Następnie sformatuj je po stronie klienta z wykrytą strefą:
const slotUTC = "2026-02-16T19:43:29.000Z";
const userTZ = Intl.DateTimeFormat().resolvedOptions().timeZone;
const localTime = new Date(slotUTC).toLocaleString("pl-PL", {
timeZone: userTZ,
hour: "2-digit",
minute: "2-digit",
hour12: false,
});
// "14:43" dla America/New_York (UTC-5)Opcja B — Pokaż obie perspektywy. Wyświetl czas lokalny dostawcy (dateTimeFromISO) obok czasu lokalnego użytkownika. To buduje zaufanie przy rezerwacjach między strefami:
Czas sesji: 20:43 Warszawa (14:43 Twój czas)
Oba podejścia działają, ponieważ API daje Ci surowe dane UTC i sformatowany czas lokalny dostawcy. Ty decydujesz, jak to zaprezentować.
Generowanie slotów: Gdzie strefy czasowe stają się trudne
Za kulisami silnik generowania slotów Timerise rozwiązuje najtrudniejsze problemy strefowe, dzięki czemu Ty nie musisz.
Kiedy usługodawca ustawia swoją dostępność jako „poniedziałek–piątek, 9:00–17:00", ma na myśli czas lokalny. Ale system przechowuje wszystko w UTC. Konwersja musi uwzględniać przejścia DST, gdzie offset zmienia się w trakcie harmonogramu.
Timerise rozwiązuje to za pomocą biblioteki date-fns-tz i trzech kluczowych funkcji:
fromZonedTime(localDate, timeZone)— konwertuje czas zegarowy na UTCtoZonedTime(utcDate, timeZone)— konwertuje UTC na czas zegarowyformatInTimeZone(utcDate, timeZone, format)— formatuje datę UTC do wyświetlenia w dowolnej strefie
Pipeline generowania działa tak:
- Harmonogram dostawcy (czasy lokalne) → konwersja do granic UTC przez
fromZonedTime - Wykrywanie nakładania slotów → czysta arytmetyka milisekund UTC, bez konwersji stref
- Filtrowanie godzin pracy →
toZonedTimeprzelicza z powrotem na czas lokalny do porównań godzin - Asemblacja wyjścia → zarówno pola
DateTime(UTC) jak iDateTimeISO(z offsetem)
To oznacza, że slot o 9:00 w Europe/Warsaw staje się prawidłowo 08:00:00Z zimą (+01:00) i 07:00:00Z latem (+02:00). Generowanie slotów obsługuje to automatycznie przez granice DST — bez ręcznej interwencji.
Praktyczne wskazówki dla deweloperów frontend
Budujesz własny frontend na Timerise? Pamiętaj o tych zasadach:
1. Zawsze wysyłaj UTC dla wejść DateTime
Skalar DateTime parsuje dane wejściowe jako UTC. Nie wysyłaj czasów lokalnych bez sufiksu Z — zostaną błędnie zinterpretowane jako UTC:
✅ Poprawnie: "2026-02-16T19:43:29.000Z"
❌ Źle: "2026-02-16T20:43:29" (traktowane jako UTC, przesunięcie o 1 godzinę)
2. Wiedz, kiedy użyć wejść DateTimeISO vs DateTime
Pola wyjściowe DateTimeISO są obliczane przy każdym zapytaniu z przechowywanej wartości UTC i strefy rezerwacji. Ale DateTimeISO jest też akceptowany jako dane wejściowe — bookingCreate, bookingReschedule, bookings i services obsługują parametry dateTimeISOFrom / dateTimeISOTo. Używaj wejść DateTimeISO, gdy masz już czas lokalny z offsetem (np. z kalendarza użytkownika). Używaj wejść DateTime (UTC), gdy wykonujesz arytmetykę czasową lub gdy już przekonwertowałeś na UTC.
3. Obsługuj brak strefy czasowej z wdziękiem
Starsze rekordy rezerwacji mogą nie mieć pola timeZone, co powoduje, że dateTimeFromISO zwraca null. Zawsze miej zapasowe rozwiązanie z polem UTC dateTimeFrom:
const displayTime = booking.dateTimeFromISO ?? new Date(booking.dateTimeFrom).toLocaleString();4. Wykryj strefę raz, używaj wszędzie
Wywołaj Intl.DateTimeFormat().resolvedOptions().timeZone raz przy ładowaniu strony i zapisz wynik. Przekazuj ten sam identyfikator IANA do każdej mutacji bookingCreate lub bookingReschedule. Spójność zapobiega rozbieżnym rekordom stref. Dla agentów AI strefa czasowa powinna być pobrana z profilu użytkownika lub kontekstu sesji i przekazywana konsekwentnie w każdym wywołaniu API.
5. Pamiętaj: Dni DST nie zawsze trwają 24 godziny
Jeśli budujesz widok dzienny kalendarza, nie zakładaj, że 24 * 60 * 60 * 1000 milisekund to jeden dzień. Podczas przejść DST dzień lokalny może trwać 23 lub 25 godzin. Używaj funkcji bibliotecznych (jak date-fns) do arytmetyki dat zamiast surowych obliczeń milisekundowych.
DateTimeISO jako dane wejściowe: Wysyłaj czasy lokalne bezpośrednio
Poza byciem skalarem wyjściowym, DateTimeISO jest akceptowany jako typ wejściowy dla zapytań i mutacji. Oznacza to, że możesz wysyłać czasy lokalne z ich offsetem UTC bezpośrednio — API parsuje offset i konwertuje wewnętrznie do UTC.
To znacząca poprawa dla agentów AI i aplikacji opartych na LLM. Zamiast konwertować czasy lokalne na UTC przed każdym wywołaniem API, agent może przekazać czas lokalny użytkownika bez zmian z offsetem — mniej logiki konwersji, eliminacja klasy błędów, prostszy i bardziej niezawodny kod agenta.
Następujące zapytania i mutacje akceptują parametry dateTimeISOFrom / dateTimeISOTo:
- Zapytania:
bookingsiservices— filtrowanie wyników po zakresie czasu lokalnego - Mutacje:
bookingCreateibookingReschedule— określanie czasu rezerwacji w czasie lokalnym
mutation CreateBooking {
bookingCreate(
serviceId: "srv_12345"
dateTimeISOFrom: "2026-03-15T09:00:00+01:00"
dateTimeISOTo: "2026-03-15T10:00:00+01:00"
) {
bookingId
status
}
}query GetBookings {
bookings(
dateTimeISOFrom: "2026-03-15T00:00:00+01:00"
dateTimeISOTo: "2026-03-16T00:00:00+01:00"
) {
bookingId
dateTimeFrom
dateTimeFromISO # czas lokalny z offsetem UTC (np. "2026-03-15T09:00:00+01:00")
}
}Bez ręcznej konwersji UTC. Bez arytmetyki offsetów. API to obsługuje.
Dlaczego GraphQL + pełna obsługa stref to najlepszy stack dla agentów AI
Błędy stref czasowych to nie przypadki brzegowe — to zabójcy przychodów. Każdy błędny czas spotkania oznacza:
- Niestawiennictwo zdezorientowanych klientów
- Zgłoszenia do supportu od sfrustrowanych użytkowników
- Podwójne rezerwacje, gdy sloty nakładają się przez przejścia DST
- Odpowiedzialność prawna w planowaniu medycznym lub prawnym
Gdy agenci AI obsługują rezerwacje autonomicznie, stawka jest jeszcze wyższa. Nie ma człowieka w pętli, który złapie błąd strefy zanim dotrze do klienta. API musi być poprawne z założenia.
Tutaj kombinacja GraphQL i pełnej obsługi stref czasowych Timerise tworzy unikatowo wydajny stack dla autonomicznych agentów:
- Bezpieczeństwo typów na poziomie schematu — skalary
DateTime,DateTimeISOiTimeZoneuniemożliwiają agentowi wysłanie błędnych danych czasowych. Schema to kontrakt. - Introspekcja — agent AI może odpytać sam schemat o dostępne pola i typy. Bez parsowania dokumentacji, bez ryzyka halucynacji.
- Precyzyjne pobieranie danych — agent żąda tylko potrzebnych pól czasowych. Bez over-fetchingu, bez marnowania tokenów.
- Jednoznaczna semantyka stref — każda odpowiedź zawiera zarówno UTC, jak i czasy z offsetem. Agent zawsze dokładnie wie, jaką strefę reprezentuje wartość.
- Wejścia
DateTimeISO— agenci wysyłają czasy lokalne bezpośrednio, eliminując konwersję UTC po stronie klienta.
REST API pozostawia interpretację stref czasowych wywołującemu. GraphQL API z typizowanymi skalarami stref czasowych sprawia, że nie da się źle zinterpretować znacznika czasu. Dla agentów AI działających na skalę w wielu strefach czasowych to nie wygoda — to wymóg.
API Timerise przejmuje złożoność. Twój frontend — lub Twój agent AI — przejmuje doświadczenie. Twoi użytkownicy widzą właściwy czas, za każdym razem.
Gotowy budować rezerwacje świadome stref czasowych z agentami AI?
Odkryj dokumentację Timerise API →
Czytaj: GraphQL — idealny backend dla agentów AI →
Testuj zapytania GraphQL na żywo →
<br>