Data og stabil drift
Tidszoner og sommertid: få bookinger og planlagte jobs til at ske på det rigtige tidspunkt
Tid er ikke bare en tekst som “kl. 08.00”. En booking, et oprettelsestidspunkt og en rapport, der skal køre hver morgen, betyder tre forskellige ting. Hvis appen gemmer dem ens, kan påmindelser komme en time forkert, datoer flytte sig for brugere i en anden tidszone, eller et job køre to gange, når uret stilles tilbage.
Kortlæg hvad tidspunktet betyder i forretningen
Start med de funktioner, hvor en forkert time eller dato får en reel konsekvens. Skriv betydningen ned, før I vælger databasefelt eller JavaScript-type.
| Betydning | Eksempel | Det skal bevares |
|---|---|---|
| Et præcist øjeblik | Betaling modtaget eller loghændelse | Et absolut tidspunkt i UTC |
| En lokal aftale | Møde kl. 09.00 hos kunden | Lokal dato, klokkeslæt og navngiven tidszone |
| En kalenderdato | Fakturadato eller fødselsdag | Datoen uden et opdigtet klokkeslæt |
| En lokal gentagelse | Rapport hver hverdag kl. 07.00 | Regel, lokal tid og tidszone |
| Et fast interval | Kontrollér status hver 15. minut | Varighed og seneste eller næste kørsel |
Et døgn på 24 timer er ikke altid det samme som “samme lokale klokkeslæt i morgen”. Den forskel skal være en produktbeslutning, ikke et tilfældigt resultat af serverens standardtidszone.
Gem betydningen – ikke kun den viste tekst
Brug UTC til at sammenligne og sortere præcise øjeblikke. Bevar samtidig den lokale kontekst, når brugeren har valgt et klokkeslæt i et bestemt område. En fast forskydning som +01:00 er ikke en erstatning for en zone som Europe/Copenhagen, fordi den faste forskydning ikke indeholder regler for sommertid eller senere ændringer.
- Hændelser der allerede er sket
- Gem et absolut tidspunkt. Formatér først til brugerens zone, når det vises.
- Fremtidige lokale aftaler
- Gem lokal dato og tid, IANA-zone og det beregnede øjeblik, så både intention og aktuel fortolkning kan kontrolleres.
- Datoer uden klokkeslæt
- Gem dem som datoer. Midnat i UTC kan ellers blive til dagen før i en vestlig tidszone.
- Gentagne lokale tider
- Gem selve gentagelsesreglen og zonen. Beregn kommende kørsler med aktuelle tidszoneregler.
Gør tidszonen tydelig ved input og visning
En browser, server og database kan have tre forskellige standardtidszoner. Lad derfor ikke en tekst uden zone blive fortolket tilfældigt. Appen skal kende den relevante zone fra virksomheden, lokationen, brugeren eller den konkrete aftale.
- Vis konteksten: Skriv for eksempel “09.00 dansk tid” eller vis zonen, når brugere kan sidde forskellige steder.
- Validér på backend: Afvis ugyldige eller ufuldstændige værdier frem for at lade serverens lokale indstilling gætte.
- Send entydige API-værdier: Brug et dokumenteret ISO-format med offset eller UTC for præcise øjeblikke, og separate felter for lokal tid og zone, når intentionen skal bevares.
- Formatér ved kanten: Gem ikke en dansk visningstekst som den eneste sandhed. Formatér dato og tid til brugerens sprog og zone i brugerfladen.
- Vær varsom med forkortelser: Korte zonenavne kan være tvetydige. Brug IANA-navne i data og konfiguration.
Tag stilling til timer, der mangler eller findes to gange
Når uret stilles frem, findes nogle lokale klokkeslæt ikke. Når uret stilles tilbage, kan samme lokale klokkeslæt forekomme to gange. Appen skal have en synlig regel for begge situationer.
- Afvis eller forklar en tid, der ikke findes. Lad brugeren vælge en anden tid, eller vis tydeligt hvilken justering appen foretager.
- Bed om præcisering ved en tvetydig tid. Vælg ikke automatisk den første eller anden forekomst, hvis forskellen har betydning.
- Gem den valgte fortolkning. En lokal tid, zone og beregnet UTC-værdi gør beslutningen efterprøvbar.
- Gennemgå tilbagevendende aftaler. En ugentlig aftale skal normalt følge det lokale klokkeslæt; et teknisk interval kan have brug for en fast varighed.
Vælg databasefelt efter tidsdataens betydning
PostgreSQL skelner mellem timestamp with time zone og timestamp without time zone. En tidszonebevidst værdi konverteres og gemmes internt som UTC, men den oprindelige IANA-zone bevares ikke automatisk som en del af værdien. Gem derfor zonen i et separat felt, når lokal intention har betydning.
- Brug et tidszonebevidst timestamp til hændelser og beregnede kørselsøjeblikke.
- Brug en egentlig datotype til datoer uden klokkeslæt.
- Gem lokal dato og tid separat, når en fremtidig aftale skal kunne genfortolkes efter sin navngivne zone.
- I en dokumentdatabase bør felterne have samme tydelige betydning: et absolut timestamp, en zone og eventuelt en lokal dato eller gentagelsesregel.
- Dokumentér serverens, databasens og jobplatformens standardtidszone. Lad den ikke være en skjult forretningsregel.
Planlæg jobs efter enten lokal tid eller fast kadence
“Hver dag kl. 07.00 i København” og “for hver 24 timer” er forskellige krav. Vælg det ene bevidst, og skriv zone eller UTC eksplicit i schedulerens konfiguration.
- Lokal forretningstid: Brug en navngiven tidszone, når rapporten eller påmindelsen skal følge lokalt klokkeslæt gennem sommer- og vintertid.
- Præcis teknisk kadence: Brug UTC eller et reelt interval, når der skal gå samme antal minutter eller timer mellem kørsler.
- Kend platformen: Google Cloud Scheduler beskriver mulige uregelmæssigheder omkring sommertid. Azure Functions har forskellige muligheder afhængigt af operativsystem og hostingplan. Firebase-planer bruger Cloud Scheduler.
- Gør jobbet sikkert at gentage: En scheduler eller retry kan udløse samme arbejde mere end én gang. Brug en stabil nøgle for perioden og undgå dobbelt mail, faktura eller sletning.
- Planlæg indhentning: Beslut om et overset job skal køres senere, springes over eller kræve manuel godkendelse.
Langvarigt arbejde, retries og dubletter er dækket mere detaljeret i den separate guide om baggrundsjob og jobkøer.
Overvåg både planlagt og faktisk kørsel
Et grønt scheduler-ikon beviser ikke, at forretningsopgaven blev udført på det rigtige tidspunkt. Log den planlagte kørsel, den faktiske start, den anvendte zone, periodens stabile nøgle og resultatet uden at kopiere følsomme data.
- Alarmér på manglende resultat og usædvanlig dobbeltkørsel – ikke kun tekniske exceptions.
- Vis seneste vellykkede kørsel og næste forventede kørsel i en intern driftsvisning.
- Brug revisionslog, hvis en administrator ændrer tidszone, gentagelsesregel eller manuel kørselsstatus.
- Dokumentér hvordan et job køres sikkert manuelt, og hvordan en forkert kørsel afgrænses.
Test over tidszoneskift – ikke kun på dagens dato
Brug faste testure og navngivne zoner. Find de relevante skift i tidszonedataene for de områder, appen understøtter, og test på begge sider af skiftet.
- Opret en tid lige før, under og efter overgangen til sommer- og vintertid.
- Bekræft hvad appen gør med en lokal tid, der ikke findes, og en tid der findes to gange.
- Vis samme hændelse for brugere i to forskellige zoner og kontrollér både dato og klokkeslæt.
- Test dato-felter nær midnat, så en fakturadato eller fødselsdag ikke flytter dag.
- Simulér forsinket, gentaget og overset jobkørsel, og kontrollér den forretningsmæssige effekt.
- Test efter opdatering af runtime eller tidszonedata, især hvis appen har aftaler langt frem i tiden.
Typiske fejl
- Alt gemmes som UTC: Det absolutte øjeblik gemmes, men brugerens lokale intention og zone går tabt.
- Alt gemmes som lokal tekst: Appen kan ikke afgøre, hvilket øjeblik teksten beskriver.
- Fast offset bruges som zone:
+01:00ved ikke, hvornår lokale regler skifter. - Serverens standard styrer: Koden virker lokalt, men ændrer adfærd i cloudmiljøet.
- Dato bliver til midnat: En ren kalenderdato flytter dag, når den konverteres mellem zoner.
- Cron-udtrykket står alene: Ingen ved, om det fortolkes som UTC eller lokal tid.
- Schedulerens start tælles som succes: Jobbet blev udløst, men rapporten, mailen eller sletningen blev ikke færdig.
- Sommertid testes manuelt i produktion: Fejlen opdages først den nat, hvor kunderne rammes.
Tjekliste til tid og planlagte jobs
- ☐ Kritiske bookinger, deadlines, datoer, påmindelser og jobs er kortlagt.
- ☐ Hvert felt er klassificeret som øjeblik, lokal aftale, dato, gentagelse eller interval.
- ☐ Præcise øjeblikke gemmes entydigt og vises først derefter i brugerens zone.
- ☐ Lokal dato, tid og IANA-zone bevares, når brugerens intention kræver det.
- ☐ Rene datoer gemmes uden et opdigtet klokkeslæt.
- ☐ API-formater og standardtidszoner er dokumenteret og valideret.
- ☐ Reglen for manglende og dobbelte lokale timer er besluttet og synlig for brugeren.
- ☐ Hvert planlagt job bruger bevidst lokal zone, UTC eller fast interval.
- ☐ Gentagelse, forsinkelse og overset kørsel kan håndteres uden skjulte sideeffekter.
- ☐ Logs viser planlagt tid, faktisk tid, zone, periodens nøgle og resultat.
- ☐ Tests dækker tidszoneskift, midnat, flere brugerzoner og runtime-opdatering.
- ☐ Der findes alarm og runbook for manglende eller dobbelt forretningsresultat.
Relaterede guides
Officielle kilder
Tidsfunktioner og scheduler-indstillinger afhænger af runtime, database og hostingplan. Følg den aktuelle dokumentation til den stack, appen bruger, og verificér den faktiske konfiguration i hvert miljø.
Virker appen, men er tid stadig en skjult risiko?
Startklar er til virksomheder med en fungerende AI-bygget app, som skal kunne bruges trygt af medarbejdere eller kunder. Her kan datamodellen, planlagte jobs, tests og overvågning blive gennemgået i den stack, appen faktisk bruger.
Se Startklar-forløbet