PHP 5.3 : Manipulation de dates

12 novembre 2008date, php, php-5.3
 Cet article a été rédigé il y a plusieurs années et peut ne plus être tout à fait à jour…

Les exemples correspondant à ce point se trouvent dans le répertoire "date".

Cet article va présenter deux fonctions ajoutées à PHP 5.3, en rapport avec la manipulation de dates :

Sommaire :


date_create_from_format

Une difficulté à laquelle nous autres développeurs de sites francophones sommes souvent confrontés est la récupération d'une date saisie par l'utilisateur.
En effet, les fonctions de date de PHP <= 5.2 ont parfois quelques problèmes de reconnaissance de notre format de dates...

Typiquement, depuis PHP 4.x, nous aurions tendance à utiliser quelque chose de la forme suivante :

<?php
date_default_timezone_set('Europe/Paris');
$ts1 = strtotime('25/04/2008 13:30:00');
var_dump(date('Y-m-d', $ts1));

Ce qui nous renvoit en sortie :

string '1970-01-01' (length=10)

Ce qui n'est de toute évidence pas ce que nous attendions...

A partir de PHP 5.1, nous essayerions la syntaxe suivante :

<?php
date_default_timezone_set('Europe/Paris');
$date = date_create('25/04/2008 13:30:00');
var_dump($date);

Et nous obtiendrions :

boolean false

Autrement dit, une seconde fois, une date non reconnue... Ce qui n'est toujours pas ce que nous souhaitons !

Pour arranger les choses, PHP 5.3 introduit une nouvelle fonction : date_create_from_format.
Elle permet de préciser, en premier paramètre, le format à utiliser pour lire la date -- celle-ci étant passée en second paramètre.

Typiquement, pour reconnaitre une date au format couramment utilisé en France, nous pouvons, à partir de PHP 5.3, écrire ceci :

<?php
date_default_timezone_set('Europe/Paris');
$date = date_create_from_format('d/m/Y H:i:s', '25/04/2008 13:30:00');
var_dump($date->format('Y-m-d'));

Ce qui nous donne en sortie :

string '2008-04-25' (length=10)

C'est-à-dire, exactement la date attendue !

Encore une raison pour laquelle j'ai hâte de travailler avec PHP 5.3 !


date_get_last_errors

PHP 5.3 introduit aussi une nouvelle fonction dont le but est de permettre la récupération des erreurs survenues lors de la lecture d'une date : date_get_last_errors
Cette fonction peut être appelée à la suite d'une autre méthode de manipulation de date, et renverra les éventuelles erreurs levées par celle-ci.

Voici quelques exemples :

<?php
date_default_timezone_set('Europe/Paris');
date_create_from_format('d/m/Y H:i:s', '25/04/2008 13:30:00');
var_dump(date_get_last_errors());

Et :

<?php
date_default_timezone_set('Europe/Paris');
$date = date_create('2009-02-06T14:53:27+01:00');
var_dump(date_get_last_errors());

Ces deux portions de code provoquent toutes deux l'affichage du dump suivant :

array
  'warning_count' => int 0
  'warnings' =>
    array
      empty
  'error_count' => int 0
  'errors' =>
    array
      empty

En effet, ces deux premières portions de code sont correctes : elle n'entrainent la génération d'aucune erreur, ni d'aucun avertissement.
Des cas où la nouvelle fonction date_get_last_errors ne nous apprend rien, donc, si ce n'est pour confirmer ce que nous savions déjà : nos dates sont correctes ^^

Passons maintenant à un cas plus intéressant :

<?php
date_default_timezone_set('Europe/Paris');
$date = date_create('2009-13-31');
var_dump(date_get_last_errors());

Cet exemple-ci provoquera l'affichage de la sortie suivante :

array
  'warning_count' => int 0
  'warnings' =>
    array
      empty
  'error_count' => int 1
  'errors' =>
    array
      6 => string 'Unexpected character' (length=20)

La date "2009-13-31" est incorrecte : il n'y a pas de treizième mois dans l'année 2009 !
Malheureusement, le message d'erreur renvoyé n'est pas des plus clair ; typiquement, nous ne pouvons pas l'afficher à l'utilisateur ayant saisi la date invalide :-(

Un second exemple de date incorrecte :

<?php
date_default_timezone_set('Europe/Paris');
$date = date_create('Hello, World!');
var_dump(date_get_last_errors());

Ici, nous obtenons à la fois un avertissement, et deux erreurs :

array
  'warning_count' => int 1
  'warnings' =>
    array
      7 => string 'Double timezone specification' (length=29)
  'error_count' => int 2
  'errors' =>
    array
      0 => string 'The timezone could not be found in the database' (length=47)
      12 => string 'Unexpected character' (length=20)

Même avec une chaîne de caractères ne ressemblant aucunement à une date, les fonctions de travail sur des dates cherchent à reconnaître... des dates.
Ce qui donne des messages d'erreur parfois suprenants, par rapport à la saisie potentiellement effectuée par l'utilisateur. Ici :

  • La fonction date_create détecte deux spécifications de timezone,
  • n'en reconnait aucune,
  • et nous renvoit finalement qu'elle a détecté un caractère inattendu.

Finalement, un second cas d'erreur où les messages générés ne sont pas affichables à notre utilisateur final qui a saisi du texte dans un champ prévu pour accepter une date...

Troisième et dernier exemple :

<?php
date_default_timezone_set('Europe/Paris');
$date = date_create('2009-02-06T14:53:27+25:00');
var_dump(date_get_last_errors());

Ici, nous avons trois erreurs :

array
  'warning_count' => int 0
  'warnings' =>
    array
      empty
  'error_count' => int 3
  'errors' =>
    array
      22 => string 'Unexpected character' (length=20)
      23 => string 'Unexpected character' (length=20)
      24 => string 'Unexpected character' (length=20)

Qui ne nous apportent, une troisième fois, aucune information acceptable pour l'utilisateur final :-(

Finalement, une nouveauté qui semble bien peu intéressante, au niveau de ce que nous pourrions souhaiter renvoyer à l'utilisateur de notre application, ayant commis une erreur dans sa saisie de date...

Les calendriers de saisie de date en Javascript ont encore de toute évidence de beaux jours devant eux : même s'ils ne font pas tout et n'assurent pas la validé des données saisies, ils améliorent grandement les choses... Et sont globalement compréhensibles par l'utilisateur, contrairement à ces messages d'erreurs ^^