Hopp til hovedinnhold

Tid og dato er en essensiell del av mange IT-løsninger. Min erfaring er at det er lett å gjøre feil, og når en feil først er blitt gjort kan det gå lang tid før man oppdager den. Hvordan unngår man å havne i de vanligste tidshåndteringsfellene?

Tidssoner

Når informasjon reiser på tvers av tidssoner kan det lett oppstå misforståelser hvis man ikke er bevisst på hvordan tid håndteres. Med brukere og servere i forskjellige land, samt regler for sommer- og vintertid, kan tidssoner fort bli en kilde til feil.

Så hvordan unngår man dette? Mitt råd er å la være å bruke tidssoner. Det vil si, motiver deg selv og teamet til å bruke UTC-tid i alle ledd av informasjonsflyten, så langt det lar seg gjøre. Dette vil sannsynligvis gjøre livet enklere for dere.

UTC (Coordinated Universal Time) er en global standard for tid som er den samme uavhengig av hvor på jorda du er. UTC fungerer som en referansetid for alle tidssoner. For eksempel, norsk vintertid er UTC+1, som betyr at vi er én time foran UTC, mens sommertid er UTC+2. Noen ganger kalles UTC også Zulu-tid (Z) eller GMT (Greenwich Mean Time).

Her er noen praktiske tips for hvordan du kan håndtere tid på en konsekvent måte i systemene dine:

  1. Bruk UTC i alle tjenester: Sørg for at alle tjenestene dine opererer med UTC-tid. Dette gir et felles tidsperspektiv uavhengig av hvor i verden de kjører. Dette kan oppnås på flere måter:
    • Kjøretidsmiljø eller operativsystem: Sett tidssonen til UTC i kjøretidsmiljøet eller operativsystemet. I et Docker-basert miljø bruker imagene vanligvis UTC som standard tidssone, men dette kan også konfigureres eksplisitt.
    • Applikasjonsnivå: Hvis tjenesten er en Java-applikasjon, kan du bruke JVM-argumentet -Duser.timezone=UTC. På samme måte som alternativet ovenfor vil dette gjøre at all tidsrelatert logikk i applikasjonen bruker UTC som standard, for eksempel ved parsing eller formatering av dato og tid.
    • Eksplisitt spesifisering i kode: Du kan også spesifisere UTC-tidssonen eksplisitt når dato og tid skal opprettes, parses eller formateres. Dette gjør at intensjonen kommer tydelig frem i koden, men man kan fort glemme å bruke det konsekvent. For eksempel, for å hente nåværende dato må du bruke OffsetDateTime.now(ZoneOffset.UTC), i stedet for OffsetDateTime.now() som du kunne brukt i alternativene ovenfor.
  2. Databasehåndtering og UTC:
    • På samme måte som i en Java-applikasjon vil resultatet fra tidsfunksjoner som SYSDATE, CURRENT_TIMESTAMP() og NOW() i databasen avhenge av tidssonen til kjøretidsmiljøet eller operativsystemet. Det er derfor viktig å konfigurere databasen eller dens container image til å bruke UTC.
    • Pass også på at alle tidspunkter lagres i UTC-format i databasen. Selv om databasens egen tidssone er satt til UTC, vil man fortsatt kunne lagre innhold forskjellige tidssoner.
  3. API-integrasjoner:
    • Bruk UTC-format for alle tidsstempler som sendes eller mottas via API-er. Dette forhindrer misforståelser og sikrer konsistens på tvers av systemer.

Ved å bruke UTC på serveren kan klientene (f.eks. applikasjoner på brukerens enhet) konvertere tidsstemplene til lokal tid etter behov. Dette gir større fleksibilitet, da klienten kan tilpasse visningen av tid til den lokale tidssonen uten at serveren trenger å håndtere denne konverteringen. Fra serverens synspunkt er det, etter min erfaring, viktigst at to datoer enkelt kan sammenlignes, og sjeldent interessant hvilken tidssone brukeren er i. Situasjoner der tidssoner faktisk er relevante for serverlogikken kan inkludere automatiske bakgrunnsjobber som skal kjøres på et spesifikt tidspunkt i løpet av døgnet, eller e-poster som skal sendes ut til et fast klokkeslett, uavhengig av om det er sommertid eller vintertid.

ISO8601-standarden

Når dato og tid skal utveksles, for eksempel som del av et JSON-objekt fra backend til en Javascript-applikasjon, er det vanlig å bruke ISO8601-formatet som er den internasjonale standarden for dette formålet. Dette ser for eksempel slik ut:

  • 2024-12-17T12:00:00Z
  • 2024-12-17T13:00:00+0100

Begge disse eksemplene representerer nøyaktig samme øyeblikk, men med forskjellig tidssone. I det første eksempelet brukes Z-tidssonen (UTC), mens det andre eksempelet viser norsk vintertid (UTC+1).

Når du mottar et tidsstempel fra et API er det en fordel å konvertere stringen til en egnet type. I JavaScript brukes typisk Date-objektet. Noe som er verdt å merke seg er at Date-objektet ikke tar vare på tidssonen. Hvis du sender inn en ISO8601-dato (for eksempel "2024-12-19T12:00:00+0200") i Date-konstruktøren vil den automatisk bli konvertert til UTC og vises i lokal tid basert på enhetens innstillinger. Dette kan føre til misforståelser hvis du ikke er klar over hvordan denne konverteringen fungerer. For eksempel, hvis PC-en din er stilt inn på tidssone "Europe/Oslo" vil du få dette:

new Date("2024-12-19T12:00:00+0200").toISOString()
// '2024-12-19T10:00:00.000Z'

new Date("2024-12-19T12:00:00+0200").toLocaleString()
// '19/12/2024, 11:00:00'

Hvis du ønsker å ha kontroll over hvilket klokkeslett som vises hos sluttbrukeren kan du oppgi tidssone på denne måten:

new Date("2024-12-17T12:00:00+0200").toLocaleString(
  'en-GB', 
  { timeZone: 'Europe/Helsinki' }
)

// '17/12/2024, 12:00:00’

Siden datoen automatisk konverters til UTC har det i praksis ingen betydning hva slags tidssone som ligger i ISO-strengen fra API-et, men som nevnt tidligere er det vanlig praksis å benytte UTC-format konsekvent.

Konklusjon

Bruk alltid UTC på servere og i API-er for å unngå tidssonerelaterte problemer. Bruk ISO 8601-formatet for tidsstempler, og la klientene håndtere visningen i lokal tid. Dette sikrer et konsekvent og skalerbart system.

Flere tips:

Liker du innlegget?

Del gjerne med kollegaer og venner