Ga naar inhoud

Best practice tijdzones


Aanbevolen berichten

Even peilen:

Wat is de beste benadering voor een applicatie dat in meerdere tijdszones wordt gebruikt? 

We hebben natuurlijk Get(CurrentTimeUTCMilliseconds) om een universele tijd vast te leggen, maar dat leidt wel tot een conversievraagstuk om leesbare tijden in het systeem weer te geven (waarvoor Menno overigens een mooie CF heeft gemaakt).

De standaard entry-optie voor tijdstempels uitschakelen en calculatie instellen op Get(CurrentHostTimestamp) is ook een optie, maar leidt ook tot een display probleem als de eindgebruiker in een andere tijdzone zit.

Benieuwd naar jullie inzichten!

Link naar reactie

Voor mijzelf is evident dat je hier alleen nog de host timestamp kunt gebruiken. Dit om ervoor te zorgen dat de opgeslagen tijden eenduidig zijn. Voor de eind gebruiker kun je een berekend veld gebruiken dat er de eigen tijd voor die gebruiker mee berekent. Dit is alleen voor de presentatie van dit gegeven.

Link naar reactie

Mijn CF berekent de DST zoals deze nu in het grootste deel van de EU wordt gebruikt. Je zou mijn CF dus eigenlijk moeten uitbreiden met een stukje waarmee je DST uitschakelt.

Verder is de opmerking van Banach óók zeer terecht. Wanneer je slechts één FMServer gebruikt is dat de meest eenvoudige manier om allemaal van dezelfde absolute tijd  gebruik te maken

Dat verandert helaas als je meerdere servers gebruikt en ze met alkaar gaat laten 'praten'. UTC vanuit FM(server) is dan ook niet betrouwbaar, omdat het voor veel systeembeheerders erg moeilijk is om de juiste tijd en tijdzone op een server in te stellen. Ze synchroniseren dan wel via NTP, maar als de basisinstellingen niet kloppen, krijg je toch een heel riedeltje problemen.

Voorbeeld: je hebt een host voor je virtuele machines, die heeft ook een tijdzone. De VM's zijn verschillende smaken Windows en Linux én ook nog eens op verschillende locaties en door verschilende personen op verschilllende werkstations aangemaakt en geconfigureerd. Het is een extreem voorbeeld, maar ik heb het aan de hand gehad en de tijdsverschillen zijn erg niet van de lucht en erg lastig op te lossen. Je moet echt alles doorlopen om de zaak synchroon te krijgen :-)

Link naar reactie

Dank jullie wel! Dit is waardevolle input.

Ik verkeerde in de onterechte veronderstelling dat Get(CurrentTimeUTCMilliseconds) een host-gebaseerde timestamp oplevert! Dat is dus niet zo en dat maakt het m.i. direct onbruikbaar voor absolute tijdsregistratie, tenzij je de functie op de FMS laat evalueren, wat mij enorm ingewikkelde rompslomp lijkt.

Ik volg Banach met zijn stelling: consequent gebruik van de host-timestamp en dus nooit meer de auto-entry tijdstempel aanvinken als je een multi-tijdzone systeem bouwt waarin tijd ertoe doet.

Vervolgens moet er dus voor alle gegevens waarvoor een datum/tijd wordt weergegeven een (unstored) calculatieveld worden gebruikt waarin de tijd wordt gecorrigeerd naar de lokale datum/tijd. Althans - als men de tijdstippen in lokale tijd moet kunnen duiden.

Kan me voorstellen dat je per sessie een tijdsverschil vastlegt ten opzichte van de hosttijd, om deze correctie mogelijk te maken. Je hoeft dan eigenlijk niet eens de tijdzone op zichzelf vast te leggen. Elk tijdsverschil is goed. 

Binnen het gesloten systeem van één server heb je daarmee het probleem waarschijnlijk opgelost. 

Bij niet gesloten systemen en data-sync op basis van timestamps heb je inderdaad het probleem van de tijdverschillen (al dan niet in verschillende tijdszones en DST). Zou me kunnen voorstellen dat je hier een zelfde soort benadering toepast als hierboven: per sessie eerst het tijdsverschil bepalen, en vervolgens bij elke vergelijking op recordsniveau de tijdsverschilfactor meenemen, in de vorm van een soort globale variabele, ook bij het overzetten van de data.  

Heb een dergelijke benadering nog niet eerder hoeven toe te passen. Wel gebruikte ik een minimale margetijd om niet op elke gedetecteerd tijdsverschil een record te laten syncen, juist omdat de klokken niet 100% gelijk lopen. Overigens vaak in combinatie met een hashcode om werkelijke wijzigingen te kunnen detecteren.

Link naar reactie
9 uren geleden, Marsau zei:

Kan me voorstellen dat je per sessie een tijdsverschil vastlegt ten opzichte van de hosttijd, om deze correctie mogelijk te maken. Je hoeft dan eigenlijk niet eens de tijdzone op zichzelf vast te leggen. Elk tijdsverschil is goed. 

Je moet dan wel corrigeren voor DST, die in verschillende landen op andere momenten ingaat en soms op andere tijden . . .

Link naar reactie

dat werkt alleen voor de huidige stamps, als je een lijst hebt van bv correspondentie die over een langere periode loopt dan kan het zijn dat er in die periode één of meerdere keren een correctie moet worden doorgevoerd vanwege de DST en dan moet je weten of er DST zat in de opgeslagen tijd, of dat er DST was bij de gebruiker.

Als je de datum op de server als UTM opslaat dan heb je 1 kant al afgedekt. hoef je alleen te weten wanneer DST bij de gebruiker was zodat je daarvoor kunt corrigeren.

Link naar reactie
Op 10-6-2022 om 14:25, Infomatics zei:

dat werkt alleen voor de huidige stamps, als je een lijst hebt van bv correspondentie die over een langere periode loopt dan kan het zijn dat er in die periode één of meerdere keren een correctie moet worden doorgevoerd vanwege de DST en dan moet je weten of er DST zat in de opgeslagen tijd, of dat er DST was bij de gebruiker.

 

Ok, dat is een hele terechte opmerking! Als je alles baseert op het tijdsverschil van een bepaald moment,  krijg je fouten met DST op de betreffende datum/tijdstip. 

Dan kom ik tot de volgende inrichting':

  1. enkel en alleen hosttime-stamps vastleggen: Get(CurrentHostTimestamp)
  2. in een UTC formaat. Let op. Get(CurrentTimeUTCMilliseconds) is hiervoor niet bruikbaar!
  3. voor datum/tijd weergave aparte unstored calculatievelden waarin de UTC tijd wordt geconverteerd op basis van de tijdszone en DST van de lokatie van de gebruiker.

Tijdszone en DST (wel/niet) moeten dan sessie-parameters worden. Wellicht kan je dan on-the-fly bepalen, maar voor makkelijker lijkt het om gebruikersrecords te gebruiken waarin het gegeven wordt opgeslagen.

M.i. is er een CF nodig dat Get(CurrentHostTimestamp) omzet in een UTC, aangezien Get(CurrentTimeUTCMilliseconds) de client klok gebruikt. 

Vervolgens kan de CF als die van Menno worden gebruikt om de UTC om te zetten naar lokale datum/tijd op de layouts: uitgebreid met het DST stuk.

Ik vroeg me af of het gebruik van UTC een noodzaak is, of je m.a.w. niet ook gewoon de lokale servertijd tot norm kan verheffen, en mutatis mutandis elke timestamp kan converteren naar de lokale timezone van de gebruiker. Ik denk echter dat je dan ook hetzelfde vraagstuk krijgt met DST.

Link naar reactie
7 hours ago, Marsau said:

Ik vroeg me af of het gebruik van UTC een noodzaak is, of je m.a.w. niet ook gewoon de lokale servertijd tot norm kan verheffen, en mutatis mutandis elke timestamp kan converteren naar de lokale timezone van de gebruiker. Ik denk echter dat je dan ook hetzelfde vraagstuk krijgt met DST.

Tijdzones zijn ten opzichte van UTC. Daarmee lijkt UTC het aangewezen uitgangspunt.

Link naar reactie

Dat ligt aan de definitie die je hanteert, Get ( CurrentTimeUTCMilliseconds ) is het aantal verstreken milliseconden (getal) sinds "01-01-0001 0:00:00,0", dus als zodanig is het inderdaad een (verstreken) tijd.

FileMaker slaat tijdstempels, data (datums in Nieuwspraak) en tijden intern op als getallen en daarom kan je de UTC gemakkelijk als tijdstempel, datum of tijd noteren:

Let ( [     
    UTC = get ( CurrentTimeUTCMilliseconds )
] ;     
    List ( 
        GetAsTimestamp ( UTC / 1000 ) ; 
        GetAsDate ( Floor ( UTC / 86400000 ) ) ; 
        GetAsTime ( UTC / 1000 ) 
    )
)

 

Link naar reactie

Dank Menno, als ik een beetje had opgelet had ik kunnen zien dat de UTC functie inderdaad niet een 'dagtijd' oplevert. Dus UTC levert dus toch echt een volwaardige datetimestamp.

Vind het jammer dat Get ( CurrentTimeUTCMilliseconds ) geen variant heeft die op de host klok gebaseerd is, nu eigenlijk wel duidelijk is dat lokale timestamps uit den boze zijn als tijd-ertoe-doet in een multi-timezone systeem. 

Een calculatie/CF als hieronder zou de server UTC-timestamp kunnen leveren..

Let ( 
[ hostTS = Get (TijdstempelHuidigeHost)
; localUTC = Floor ( Get ( HuidigeTijdUTCMilliseconden ) / 1000 )
; delta = GetAsNumber ( hostTS - localUTC )
];

hostTS - delta

)

Een tweede uitdaging is de uitbreiding van jouw CF: het converteren van een willekeurig UTC naar een lokale tijd, waarbij je uitgaat van tijdzone, wel/geen DST en zo ja, is deze actief op het moment van de gegeven UTC.

Ik vraag me af wat de performance implicaties gaan zijn als je deze grappen echt implementeert.

Link naar reactie

Doe mee aan dit gesprek

Je kunt dit nu plaatsen en later registreren. Indien je reeds een account hebt, log dan nu in om het bericht te plaatsen met je account.

Gast
Antwoord op deze discussie...

×   Geplakt als verrijkte tekst.   Plak in plaats daarvan als platte tekst

  Er zijn maximaal 75 emoji toegestaan.

×   Je link werd automatisch ingevoegd.   Tonen als normale link

×   Je vorige inhoud werd hersteld.   Leeg de tekstverwerker

×   Je kunt afbeeldingen niet direct plakken. Upload of voeg afbeeldingen vanaf een URL in

×
×
  • Nieuwe aanmaken...