dimanche 25 mars 2012

JAX et les Calendar

L'équipe, dont je faisais partie, devant mettre en place des WebService utilisant JAX à rencontré un étrange phénomène.
En effet, le serveur envoyait une date (exemple : 12/05/1450 00:00:00) et le client récupérait une autre date.

Après analyse, le problème se posait dans la couche JAX.

A se sujet, un collègue à ouvert le ticket suivant chez Oracle : XMLGregorianCalendar.toGregorianCalendar() return a bag milisecond for some year.

La réponse est sans appel, il n'y a pas de problème.

JAX renvoit un GregorianCalendar via XMLGregorianCalendarImpl.toGregorianCalendar, donc un calendrier Grégorien. Or le calendrier Grégorien a été mis en place à partir de 15 octobre 1582.
Avant, le calendrier Julien était utilisé. Or entre les 2, il y a un décalage.

Voici l'explication de Wikipedia :
La réforme principale et suffisante éliminant cette dérive (et qui a été
appliquée facilement dans les autres pays par la réforme limitée du
calendrier julien) était celle du mode d’application des années
bissextiles lors des années séculaires. La différence principale entre
le calendrier grégorien et son ancêtre, le calendrier julien non réformé,
repose dans la distribution des années bissextiles.

L'introduction du calendrier grégorien comprend aussi une deuxième réforme
d’application plus délicate, le décalage grégorien qui supprima 10 jours
du calendrier.

Ces 10 jours permettaient de rattraper d’un coup le retard croissant pris
par l’ancien calendrier julien sur les dates des équinoxes depuis le
concile de Nicée, plus de 12 siècles avant, et de retrouver la concordance
entre l'équinoxe de printemps et le 21 mars calendaire. Neuf années
bissextiles ont été comptées en trop : en 500, 600, 700, 900, 1000, 1100,
1300, 1400 et 1500 suivant les nouvelles règles de calcul.
Voilà le problème.

Le GregorianCalendar contiens la date de passage du calendrier Julien à celui de Grégorien.
Cette date n'est la même quelle vienne du xml ou du new Gregorian.
La correction de cette erreur ce fait en définissant la date de changement du nouveau GregorienCalendar avec ce lui qui vient du xml via setGregorianChange().

La date du changement de calendrier venant de XMLGregorianCalendarImpl est Date(Long.MIN_VALUE).
La date du changement de calendrier créer à la main est 15 octobre 1582.