Comment mapper des heures locales historiquement précises en Java lorsque les règles de fuseau horaire changent?


J'ai une base de données qui contient des horodatages UTC (GMT+0). Voici le problème: ils se réfèrent à l'activité de facturation qui a eu lieu dans l'état de l'Indiana.

Comme certains le savent peut-être, Indiana ...

  • n'a pas du tout observé l'heure d'été avant 2006 (la plupart de l'État était EST toute l'année).
  • voté en 2006 pour rester EST, mais pour commencer à observer l'heure d'été avec le reste des États-Unis
  • révisé ses règles en 2007; le gouvernement fédéral américain révision de l'heure d'été afin que les règles de début et de fin changent

Étant donné que les horodatages de cette base de données se réfèrent à l'activité de facturation du gouvernement, il est en fait nécessaire que les horodatages UTC soient signalés comme des heures locales historiquement exactes afin de préserver l'exactitude de l'audit. Il y a donc trois scénarios qui s'appliquent uniquement à l'Indiana: les horodatages avant 2006 utilisent un ensemble complètement différent de règles de fuseau horaire que ceux entre 2006-2007, et ceux après 2007 utilisez encore un autre ensemble complètement différent de règles de fuseau horaire. Vous pouvez imaginer que cette base de données inclut une activité pour des paramètres régionaux autres que l'Indiana, et que les choses deviennent encore plus compliquées.

L'API Java Calendar and TimeZone ne contient aucune classe permettant au programmeur de créer des objets avec plus d'un ensemble de règles de fuseau horaire et ne peut donc pas être utilisée pour le mappage correct des horodatages UTC avec des heures locales historiquement précises si le fuseau horaire particulier et applicable les règles changent en cours.

J'ai réfléchi aux moyens de résoudre le problème du mappage à des heures locales historiquement précises dans les paramètres régionaux avec des règles de fuseau horaire changeantes...

  • La base de données pourrait être mise à jour afin que les horodatages UTC puissent être stockés avec le décalage horaire local et un décalage d'heure d'été. Le problème ici est que la taille de la base de données augmente un peu et si la base de données existante est grande, la mise à jour de toutes les tables peut nécessiter une mise hors ligne étendue cycle de maintenance.

  • La base de données peut être mise à jour afin que l'objet de fuseau horaire particulier approprié à cet horodatage particulier soit stocké avec chaque horodatage. Bien que je pense que les objets TimeZone sont assez légers, je vois que c'est plus flexible que ce qui précède mais encore moins souhaitable car cela nécessite de persister un objet pour chaque horodatage.

  • Une API personnalisée peut être développée qui construit un objet de fuseau horaire approprié à partir d'une base de données les règles précises pour les paramètres régionaux d'intérêt. Cette solution remplace les besoins de stockage accrus des deux solutions précédentes par la nécessité d'un traitement supplémentaire. Chaque horodatage qui devait être affiché signifierait la création d'un nouvel objet ... ou au moins l'appariement avec un objet approprié d'un pool d'objets. De plus, cela signifie créer et administrer une base de données de fuseau horaire.

Les limitations de l'API Java Time et Calendar ont permis de trouver une solution élégante à ce problème vraiment plus difficile qu'il ne devrait l'être (vous ne pouvez pas, par exemple, interroger un objet SimpleTimeZone existant et lui demander quelles règles d'heure d'été il suit sans écrire de code vraiment désordonné).

Je voudrais juste demander si quelqu'un d'autre a déjà traité une situation comme celle-ci et comment il l'a gérée.

Author: scottb, 2013-02-11

1 answers

La base de données de fuseaux horaires que vous décrivez existe déjà. Il s'appelle la base de données Olson zoneinfo, il est correct pour toutes les dates après 1970, et il est disponible en ligne.

Mieux encore, les API de date et d'heure natives de Java utilisent cette base de données. Vous pouvez charger un fuseau horaire arbitraire en utilisant java.util.TimeZone.getTimeZone(), et obtenir des décalages ou effectuer des conversions en utilisant cet objet (par exemple, en utilisant TimeZone.getOffset(long). Par exemple, vous chargeriez la zone "America/Indiana/Indianapolis" pour convertir les dates et les heures dans Indiana.

La seule chose vous ne pouvez pas faire facilement avec la base de données TimeZone est en fait interroger les règles qu'elle utilise. Pour cela, je crois que vous devrez creuser directement dans les fichiers tz. Dans la plupart des cas, cependant, juste obtenir des compensations pour des dates spécifiées devrait être suffisant.

 1
Author: duskwuff, 2013-02-11 00:00:55