Fuseaux horaires et sensibilité
1) Principes de base
UTC comme transport et stockage. Tous les temps de serveur et les clés de tri sont en UTC. Convertir en temps local « mural » - sur le bord (edge/UI) ou dans un service de formatage dédié.
La zone ≠ le déplacement. ' Europe/Kyiv ' ce n'est pas simple ' UTC+02:00 ' : les règles changent avec le temps. Stockez les ID IANA (tzdb) dans le profil utilisateur/objet, pas « + 03:00 ».
Distinction claire de l'horloge.
Wall clock (temps humain, sujet à DST).
UTC clock (échelle universelle).
Monotonic clock (pour mesurer les durées et les délais). Ne calculez jamais le délai sur une montre « murale ».
Idempotentialité et tolérance au tremblement du temps. Les systèmes doivent survivre correctement à de petites sautes NTP/décalage.
2) Modèle de données et contrats API
Événements : 'occurred _ at' (UTC, RFC 3339),' timezone '(IANA), en option' wall _ time '(local avec décalage enregistré lors de la création).
Périodes : utiliser des intervalles semi-fermés '[start, end)' en UTC ; pour les planifications humaines, stockez l'expression source + zone.
Règles répétitives : sérialisez comme RRULE/cron-équivalent + zone IANA. Déléguez la planification à un moteur qui comprend le DST.
Format de l'heure dans l'API : ISO 8601/RFC 3339 avec « Z » ou décalage explicite, par exemple « 2025-10-31T17 : 00 : 00Z ». Ne passez pas de lignes « flottantes » sans décalage.
Le versioning : modifier les règles commerciales du temps (par exemple, passer d'un pays à un UTC + 1 permanent) est la migration des configurations et le recalculage des horaires ; prendre en compte dans les schémas de version.
3) Heure d'été (DST) : ambiguitettes et laissez-passer
Les temps locaux dupliqués. À l'automne, un « 02:30 » local peut se produire deux fois. Le planificateur dans la zone doit distinguer '2025-10-26T02 : 30 + 03' et '2025-10-26T02 : 30 + 02'.
Temps locaux manqués. Au printemps, les intervalles de minutes sont « sautés » (par exemple, '02 : 00-03 : 00' n'existe pas). Le planificateur est tenu de définir une stratégie : reporter à « 03:00 », sauter ou exécuter « dès que possible ».
Recommandation : stocker la tâche comme « règle locale + zone », et matérialiser les instances réelles dans UTC à l'avance (rolling window), avec la fixation de la stratégie sélectionnée sur DST.
4) Leap seconds и time smear
Leap second. Une seconde supplémentaire est parfois insérée dans UTC. La plupart des processus d'affaires ne devraient pas « voir » 23:59:60.
Smear. Certains environnements distribuent doucement l'ajustement par fenêtre (par exemple, 12 heures ±) pour éviter les sauts.
Pratique : Consentez à une seule politique de temps pour l'ensemble du cluster (NTP/smir), logiez-la dans les métadonnées et gardez-la dans le runbook.
5) Planificateurs et modèles cron
Le danger du « cron simple ». Le cron classique ne connaît pas les zones DST et IANA. Utilisez les moteurs où le planning est lié à la zone (Quartz-class, Cloud Scheduler-Services, Kubernetes CronJob avec la zone via le contrôleur/Amirassion).
Matérialisation des horaires. Pour plus de fiabilité, matérialisez les N prochains lancements en UTC (par exemple pendant 7 à 30 jours), stockez le cursor et déterminez la politique sous DST.
Idempotentialité des tâches. Ключ deduplication: `(job_id, scheduled_at_utc)`; le redémarrage ne doit pas faire double emploi avec les effets secondaires.
Le glissement de l'horloge. En cas de longues pauses ou d'incidents, décidez si vous voulez faire un catch-up (exécuter le saut) ou skip. Configurez le per-job.
6) Temps dans les protocoles et files d'attente
Pneus d'événement (Kafka/Pulsar). Gardez 'event _ time' et 'ingest _ time' séparément. Pour les recalculs rétrospectifs, utilisez 'event _ time'.
Les consommateurs idempotent. Lors de la remise répétée, orientez-vous vers la clé d'événement et 'event _ time'plutôt que vers le décalage dans le lot.
Trier et fenêtres. Les fenêtres « en 24 heures sur l'heure locale du magasin » calculent les intervalles UTC obtenus à partir des règles locales d'une zone spécifique à une date donnée.
7) Logs, traces, métriques
Norme de temps unique : toutes les logs techniques et métriques en UTC (avec indication « Z »). L'affichage dans les dashboards est localisé pour l'utilisateur.
Traces : passez 'trace _ start _ utc', 'durée _ ms'sur l'horloge monotone. Ne soustrayez jamais le temps « mural ».
Rapports d'entreprise : formez « 24 heures » dans la zone du domaine (par exemple, « Europe/Paris » pour la taxe française) et non par UTC. Documenter clairement.
8) Profils et contenus personnalisés
Профиль: `preferred_timezone` (IANA), `preferred_locale`, `currency`, `week_start` (Mon/Sun).
Entités multisones : pour les équipes/organisations, stockez une « zone de domaine » (par exemple, magasin/avocat) indépendamment de la zone personnelle du membre.
Notifications : calculer une « horloge silencieuse » dans la zone utilisateur ; envoyer à partir de la fenêtre UTC, avec sécurité à DST.
9) Anti-modèles
Ne stocker que l'heure locale sans décalage/zone.
Cochez le décalage '+ hh : mm' au lieu de l'IANA.
Compter les durées à travers la différence de deux temporisations « murales ».
Planifier par cron sans support de zone/DST.
Faire l'analyse « par jour » dans l'UTC quand la norme exige une zone locale.
Supposer que les règles de la zone soient inchangées (les pays changent de politique temporelle).
10) Test du temps
Montres contrôlées. Injectez une « horloge » dans le code (Clock/TimeProvider) pour les tests déterministes.
Jeux de cas :- Passage à l'heure d'été/hiver (prises/passes).
- Déplace l'utilisateur entre les zones (change 'preferred _ timezone').
- Modification des règles dans tzdb (mise à jour de la base - tests de régression).
- Déplacements NTP, livraison retardée des événements.
- Tests de phase. Zones aléatoires, dates, formats ; comparaison avec la bibliothèque de référence.
11) Observabilité et exploitation
Alerts : dissynchronisation NTP, retard de mise à jour tzdb, surtension des tâches cron « non exécutées » sous DST.
Dashboards : répartition des événements par zone/jour local ; les compteurs catch-up/skip.
Runbook : procédures pour changer les règles de temps dans une juridiction ; l'ordre de mise à jour de tzdb ; communication avec les titulaires d'horaires.
12) Modèles de réalisation
Time Normalization Gateway. Un service fin normalisant les temps entrants à la RFC 3339 UTC, validant les zones (IANA) et complétant le contexte.
Local-Day Builder. Bibliothèque/service qui, à partir du « jour local » et de la zone, construit les frontières UTC exactes '[start _ utc, end_utc)', compte tenu du DST.
Schedule Materializer. Un planificateur qui stocke les règles sous la forme d'une « expression locale + zone » matérialise les futures instances dans UTC et gère les conflits/omissions.
Dual-Timestamp Events. Événements avec les champs 'occurred _ at _ utc', 'wall _ time _ local', 'timezone'. L'UI est locale, l'UTC pour les systèmes.
13) Chèque de l'architecte
1. L'UTC est-il stocké partout ?
2. Les entités ont-elles une zone IANA et une stratégie de date de domaine ?
3. Le planificateur comprend DST et matérialise les instances dans UTC ?
4. Logs/métriques - en UTC ; rapports - dans la zone de domaine ?
5. Timaoutes/Retrai - sur une montre monotone ?
6. La mise à jour de tzdb est automatisée et surveillée ?
7. Les tests couvrent le changement de règles, les prises/sauts de minutes ?
14) Mini recettes (pseudo-code)
Convertir un « jour ouvrable » local en intervalle UTC
function localDayToUtcInterval(dateLocal, tz):
startLocal = combine(dateLocal, 00:00) in tz endLocal = startLocal + 1 day startUtc = toUTC(startLocal) // учитывает DST endUtc = toUTC(endLocal)
return [startUtc, endUtc)
Matérialisation d'un planning répétitif
inputs: rrule, tz, windowStartUtc, windowEndUtc for each localOccurrence in expand(rrule, tz, [windowStartUtc, windowEndUtc] projected to tz):
emit occurrence { scheduled_at_utc = toUTC(localOccurrence), tz }
Clé idempotent de lancement de la tâche
dedupe_key = hash(job_id + scheduled_at_utc.toString())
15) Sécurité et conformité
Audit : stockez les deux projections temporelles (UTC et locale) pour concilier les revendications de l'utilisateur (« on m'avait promis avant 23h00 Lima ») avec la chronologie du serveur.
Réglementation : les périodes de déclaration sont formées dans les zones requises (taxes, limites de jeu responsables, restrictions de commercialisation « par heure »).
Vie privée : fuseau horaire - paramètres personnels, mais pas d'identification précise des données ; traiter dans le cadre des politiques générales de confidentialité.
Conclusion
La « sensibilité au temps » ne concerne pas le format de la date, mais les limites architecturales de la responsabilité : où stocker, où convertir, comment planifier et comment prouver l'exactitude. L'unification au niveau UTC, les zones IANA explicites, les planificateurs compétents, les doubles temps et les monotones transforment le temps de la source des incidents en un service d'infrastructure prévisible.
Articles connexes de la section Architecture et protocoles (recommandé) :
- GeoDNS et géo-routage ; Équilibrage de charge ; L'observation des événements dans le temps ; Modèles Cron et matérialisation des horaires ; Restrictions régionales et 24 heures sur 24.