Gestion des timestamps + TZ sur stack Java (appli + DB)

Gestion des timestamps + TZ sur stack Java (appli + DB) - Java - Programmation

Marsh Posté le 07-06-2013 à 11:47:43    

Bonjour à tous,
 
Débat commencé ici, j'ai des choses à clarifier et appliquer ça à la stack Java complète, pas seulement la DB.
 
La stack :
- JodaTime pour les dates ;
- Hibernate pour l'ORM ;
- Jadira pour le support du mapping de JodaTime ;
- PostgreSQL pour la DB.
 
Je stocke et affiche des événements relatifs à mes utilisateurs, genre "s'est gratté la tête le lundi 12 janvier à 16h46". La date est rentrée par l'utilisateur, et peut être modifié. Si je décide que je me suis gratté la tête ce jour là à cette heure, c'est donc sur ma timezone. Quel que soit mon format de stockage, je devrais être en mesure de reservir à l’utilisateur l'heure exacte entrée.
 
Sur BlaBla@SQL, le conseil est de stocker la date en UTC, et éventuellement la TZ pour refiler ça à l'utilisateur ensuite (c'est mon cas).
 
Le mapper 'org.jadira.usertype.dateandtime.joda.PersistentDateTimeWithZone' me permet ça, avec le datetime stocké d'une part, et la TZ dans une autre colonne. Si j'ai tout suivi, la datetime devrait être en UTC ('08:40' s'il est '10:40' à Paris) ?
 
Évidemment, ça ne fonctionne pas comme je le souhaite, donc questions :o
 
Lorsque l'utilisateur saisie ses données, je récupère sa TZ dans le paramètre de datetime. Je créé le DateTime Joda en fonction, DateTime qui se balade jusqu'à la couche Hibernate tel quel.
 
Si je le laisse comme ça, il est stocké (pour une entrée aujourd'hui à 10h40) comme '2013-06-07 10:40:00' et 'Europe/Paris{+02:00}'. Si j'ai bien suivi, le datetime devrait être UTC, et donc '2013-06-07 10:40:00' ?
 
C'est quoi le moyen le plus propre, je sauvegarde la TZ dans un champ à part, puis converti en UTC ? Si c'est le cas, je dois me débrouiller avec 'org.jadira.usertype.dateandtime.joda.PersistentDateTime' plutôt que la version gérant la zone.
 
Une autre méthode, un truc que j'ai raté ?
 
De même, je lis beaucoup qu'une bonne pratique consiste à n'utiliser que l'UTC en interne à la JVM, pour ce qui est calculs et intervalles. Vous êtes OK avec ça ?
La seule méthode que je connaisse pour ça (portable d'une lib à l'autre), c'est -Duser.timezone=UTC, sauf que ça vient écraser la TZ fournie par l'utilisateur, et donc je suis encore fucké.
 
Merci d'avance [:romf]

Reply

Marsh Posté le 07-06-2013 à 11:47:43   

Reply

Marsh Posté le 08-06-2013 à 21:04:29    

Si tu veux couvrir tous les cas, voici ce que tu dois stocker:
 
Table Event:
* La DateTime en UTC;
* La TimeZone à l'input.
Table User:
* La TimeZone de visualisation.
 
Alors, après, quand on parle de TimeZone, ce n'est pas +02 comme j'ai vu dans l'autre poste, mais bien l'identifiant de la TZ, sinon tu perds l'info du DST.
 
Avec ces trois information, tu peux:
* ordonner de manière absolue les évènements de plusieurs utilisateurs dans des TZ différentes
* Afficher l'info telle qu'elle a été entrée par l'utilisateur (pour des audits)
* Afficher l'info relative à la timezone actuelle de l'utilisateur.


Message édité par gizmo le 08-06-2013 à 21:05:19
Reply

Marsh Posté le 10-06-2013 à 08:56:20    

gizmo a écrit :

Si tu veux couvrir tous les cas, voici ce que tu dois stocker:

 

Table Event:
* La DateTime en UTC;
* La TimeZone à l'input.
Table User:
* La TimeZone de visualisation.

 

Ce que j'en ai conclu également :jap:

 
gizmo a écrit :


Alors, après, quand on parle de TimeZone, ce n'est pas +02 comme j'ai vu dans l'autre poste, mais bien l'identifiant de la TZ, sinon tu perds l'info du DST.

 

De ce que j'ai pu voir, on stocke les deux ('Europe/Paris{+02:00}'), offset + DST offset pour reconstruire le timestamp, nom de la TZ au cas où il y ai des changements d'offset dans le futur.

 

Reste la partie Java, à savoir ne traiter qu'avec les valeurs UTC. Si je ne veux pas passer par '-Duser.timezone=UTC' (avec les problèmes évoqués dans mon post précédent), ça ne me laisse que deux choix : persister avant tout traitement ultérieur (c'est pas toujours le comportement souhaité), ou cloner et convertir dans les méthodes de calcul. Ou autre chose ?

 


Message édité par LeRiton le 10-06-2013 à 08:57:01
Reply

Marsh Posté le 11-06-2013 à 10:47:36    

Non, on ne stocke pas les deux, pour la simple et bonne raison que c'est a la libraire de date de savoir quand on eut lieu les changements de DST, et autres eventuels ajustements (D'ou le recent tolle sur le fait qu'Oracle ait suspendu le TZ updater pour java 6 sans releaser celui de java 7...). Mais pour joda time, tout est explique sur le site pour si jamais tu dois avoir une version plus a jour que celle qui est livree avec la version de la lib que tu utilises.
 
Pour la partie java, il me manque des infos pour pouvoir repondre correctement. Que recoit tu comme input? un long ou autre chose?

Reply

Marsh Posté le 11-06-2013 à 16:24:46    

Pour la partie Java, c'est plus une question de bonne pratique qu'un réel problème, j'ai de quoi travailler.
 
L'utilisateur transmet un timestamp sous forme de string formaté, type '2013-06-11T16:10:37.123+02:00', contenant donc l'offset de sa TZ courante. Pour le moment je n'ai donc pas le nom de sa TZ.
 

Reply

Marsh Posté le 11-06-2013 à 17:49:20    

Si tu n'as pas l'ID de la TZ, t'es potentiellement baise sur les periodes d'overlap de DST entre timezones contigues.

Reply

Marsh Posté le 11-06-2013 à 18:06:07    

Voilà.
Le timestamp fourni par l'utilisateur n'étant aujourd'hui destiné qu'à son seul usage (comprendre, pas de traitement pour plusieurs utilisateur), et cette valeur n'ayant d'importance que pour définir le moment de la journée où s'est déroulé l'évènement (mettre en exergue des comportements), je pense pour le moment stocker la valeur fournie par l'utilisateur tel quel, et éventuellement ignorer la TZ. Voir même ne plus stocker un timestamp, mais une date séparée du moment de la journée.
 
Pour faire simple je me demande si ma problématique de stockage d'un timestamp "propre" est réellement justifiée. Même si ce n'est pas le cas, merci pour tes réponses :jap:

Reply

Marsh Posté le 11-06-2013 à 21:14:13    

pourquoi pas stocker des Instants directement ?

Reply

Marsh Posté le 12-06-2013 à 08:25:38    

souk a écrit :

pourquoi pas stocker des Instants directement ?


 
Je pensais plus à LocalTime + LocalDate, mais effectivement, Instant à l'air de convenir. Quel avantage tu lui verrais ?

Reply

Marsh Posté le 12-06-2013 à 09:33:35    

pas stocker de time zone dans tes dates dans la DB donnent plusieurs avantages:
- c'est plus futur proof dans le sens ou si il y a des changements dans les DST ou autres, ce sera plus simple de mettre a jour ton app que ta DB  
- tu parles de stocker des DateTime en UTC => la seule facon d'etre sure c'est d'avoir toute une batterie de test, mais rien ne va empecher un script de contourner cela (par exemple un script qui repare des trucs... ). Stocker des Instant sera verifie par le compilateur dans ton app, et les scripts externes a ton app verront qu'ils doivent balancer des purs timestamp donc pas de surprises
 
surement d'autres avantages, dans tous les cas, je ne vois pas ce que stocker des DateTime en UTC apporteraient de plus (au contraire j'aurais tendance a voir que des inconvenients)

Reply

Marsh Posté le 12-06-2013 à 09:33:35   

Reply

Marsh Posté le 12-06-2013 à 10:06:50    

Je me suis mal exprimé : quel avantage tu verrais face à LocalTime + LocalDate ? *

 

Pour le reste je suis d'accord :jap:

 

* Edit : d'ailleurs, ça revient à "quelle différence entre Instant et LocalDateTime ?"
LocalDateTime me parait répondre à "d'un point de vue extérieur, fourni par un utilisateur et valable uniquement pour lui".

 

Redit : http://stackoverflow.com/a/2658607 m'a l'air de répondre à cette question, du moins sur l'utilité de LocalDateTime. Ca à l'air de coler à ce que je souhaite, ton avis souk (par rapport à ta proposition de Instant) ?


Message édité par LeRiton le 12-06-2013 à 11:19:37
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed