dimanche 4 décembre 2011
Retour vers le passé et voyage dans le temps avec Zend_Date
Publié par Infinite Loop, à 09 h 43
0 commentaire
Un client se plaignait d'avoir entré une date et que malgré tout, ça affichait la mauvaise année à l'écran. On croyait avoir affaire à un code 18 de sa part mais comme c'était reproductible, nous avons dû nous creuser les méninges pour trouver la source du problème.
En examinant le code, tout semblait conforme : la valeur de la date, la valeur stockée, la localisation (qui aurait pu jouer des tours) et le format d'affichage spécifié. Pour trouver d'où provenait l'erreur, j'ai utilisé la même méthode décrite à mon dernier billet en faisant des appels en boucle. Avec un peu de chance, peut-être que quelque chose en resortirait.
$locale = new Zend_Locale('fr_CA');Remarquez ce qui se passe dans le calcul lorsqu'on change d'année :
$date = new Zend_Date('2011-12-04', false, $locale);
$i = 0;
do{
echo $date->get('dd MMMM YYYY');
$date->add(1, Zend_Date::DAY);
echo BR; // constante
$i++;
} while($i < 60);
Nom de Zeus! Où est passé le 1er janvier 2012 ? On croirait à une déchirure du continuum espace-temps puisqu'on se retrouve soudainement au 1er jour de 2011 pour ensuite revenir en 2012 à l'itération suivante.
Pourquoi ? Ça m'enrageait un peu car ce n'était pas la première fois que j'avais des mauvaises surprises avec les dates de PHP (@pparadis avait raison). Pour les besoins du projet, le composant Zend_Date avait été retenu pour manipuler et calculer des dates et du temps, configuré avec un type de format autre que celui natif de PHP (plus intuitif que "j F Y"). Et nous ne nous attendions pas à ce type de comportement. À vrai dire, le programmeur aurait eu intérêt à mieux lire la documentation car de ce que j'ai trouvé, il existe une différence minime mais fondamentale entre les formats yyyy écrits en minuscules et majuscules :
- YYYY pour l'année ISO
- yyyy pour l'année réelle
Sinon, voici un autre exemple qui illustre mieux la représentation calendrier. Utilisez le même snippet de code ci-haut et modifiez la date initiale pour "2010-01-01". On s'attendrait que le 1er affichage indique 1er janvier 2010. Pourtant, la même logique s'applique.
Encore une fois, si on se réfère au calendrier, les trois premiers jours de 2010 sont dans la dernière semaine de 2009. Pour faire simple, YYYY retourne l'année du 1er jour de la semaine où se trouve la date demandée. Le format yyyy retourne l'année réelle.
En conclusion, trois choses :
- Lisez toujours la documentation au lieu de prendre pour acquis certaines notions. Les différences entre yyyy et YYYY sont subtiles mais importantes en même temps.
- Évitez-le format ISO pour l'affichage, à moins que vous sachiez exactement ce que vous êtes en train de faire.
- Cette démonstration utilise Zend Framework pour PHP mais comme ISO 8601 est un standard, vous risquez de rencontrer le même problème dans d'autres frameworks et langages de programmation.