10 mai 2007

date(‘d/m/Y’, strtotime(’0000-00-00′)) = ?

Category: UncategorizedRenaud @ 23h22

phpAllez, allez! Petite énigme de fin de semaine!

D’après vous, en PHP, que peut bien retourner
date('d/m/Y', strtotime('0000-00-00')), hein ?

Moi, au début, je pensais que ça allait me sortir EPOCH, donc quelque chose qui aurait dû ressembler à 01/01/1970.

Que nenni! Cela affiche 30/11/1999.

Ah… il a fallu chercher… et une fois trouvé, c’est tout à fait logique.

Cela part d’un bug PHP[1] du parser de PHP qui ne fait aucune différence entre l’année ’0′, ’00′, ’000′ ou ’0000′ et qu’il traduit inévitablement en l’an 2000. A partir de là, dans la gymnastique microprocessoromentale de PHP, il se passe les choses suivantes:

  • 0000-00-00 devient 2000-00-00
  • 2000-00-00 n’existe pas, il prend le 00 du mois et décide donc que c’est le mois précédent: 1999-12-00[2]
  • 1999-12-00 n’existe pas, il prend le 00 du jour et décide que c’est le jour précédent: 1999-11-30[3]

Nous voila donc propulsé fin novembre 1999.

Conclusion:

  • il vaut mieux avoir NULL plutôt que ’0000-00-00′ pour une date non utilisée
  • pour avoir rapidement la fin d’un mois, il suffit de se mettre au jour 00 du mois suivant. Exemple: si on veut le 31 aout 2010, il suffit d’avoir ’2010-09-00′, strtotime se chargera de revenir un jour en arrière.

Notes

[1] Contrairement à ce qui est écrit dans le rapport de bugs et ses commentaires, le bug existe toujours en PHP5

[2] De la même manière, si vous aviez le mois 13, il passerait à janvier de l’année suivante

[3] De la même manière, si vous aviez le 32 janvier, il passerait au 1er févier et si c’était le 40 janvier, vous arriveriez au 9 février.

Mots-clefs : , ,