La gestion des dates

S’il est un sujet qui me tient énormément à cœur depuis que j’ai découvert d’un côté l’API DateTime de PHP et d’un autre côté celle de JAVA au court du développement d’une application Android, c’est la gestion des dates lorsqu’on est sur le web.
De la gestion des “Il y a un jour” à  la facebook, jusqu’à  l’affichage des dates dans toutes les langues, la nécessité de la gestion des dates est omniprésente.

Quand mes errances sur les dates ont-elles commencé? A la fin de mon projet de première année de Cycle Informatique et Réseau (CIR), je me suis rendu compte que le script que j’avais produit avait non seulement été très long à  produire, mais qu’en plus il n’était pas du tout optimisé.
Premièrement j’utilisais le timestamp partout, même dans ma bdd. A priori c’est une grosse erreur. J’aimerai néanmoins apporter quelques nuances à  cette pensée :

  • Le timestamp est très compact (32 ou 64 bits selon le système d’exploitations) face au type DateTime (aaaa-mm-dd hh:ii:ss) qui prend un minimum de 6 octets.
  • un UNIX_TIMESTAMP est insensible au fuseau horraire, contrairement au type DateTime de MySQL

Vous pourrez trouver toutes les différences techniques du type DateTime de SQL sur ce topic de stackoverflow.

Dans le cas particulier de mon projet de première année, je devais gérer un système multilingue. Ce qui est rapidement casse pied avec un simple timestamp (même quand on optimisait le script que j’avais créé), ne serait-ce que parce que chaque pays à  sa manière propre d’afficher une date, indépendamment de la traduction des jours.
A ce jeu là , le timestamp est vraiment mauvais contrairement aux types plus complexes (DateTime en php, Date en JavaScript, Date enJava…) qui sont vraiment des bouffées d’air frais. Non seulement ils ajoutent du sens au programme, mais en plus ils donnent accès à des API bien plus complètes !
Pour l’exemple PHP posséde un formateur de date international IntlDateFormatter]qui fonctionne à  la perfection (nécessite l’extension intl).

Mais souvenons-nous du cas de l’affichage “mode facebook” (qui est un cas particulier de calcul finalement).
Bien des gens aiment à  faire des calculs (assez imprécis) pour tester l’antériorité (une minute, une journée, par exemple) alors que la notion d’intervalle suffit elle même à  contenir tous ces tests. Dans le cas particulier de php, ce code affichera une date “à  la facebook” :
[cc lang=”php”] $today = new DateTime;
$bestDayOfYear = new DateTime(‘2012-02-27’);
$interval = $today->diff($bestDayOfYear);
$array = ["d"=>"jours", "y"=>"années", "m"=>"mois", "h"=>"heures", "i"=>"minutes","s"=>"secondes"];
$facebook ="";
foreach((array)$interval as $key=>$value){
if($value > 0){
if(isset($array[$key])){//php ajoute un champ qui ne nous intéresse pas
$facebook .= $value. $array[$key];
}
}
}
echo $facebook;[/cc]

Si ce n’est le fait que php ajoute un champ “days” dans interval, il faudra avouer que ce code a l’avantage d’être extrêmement lisible et d’avoir un sens totalement transparent !

Je dois aussi avouer que lorsque j’ai dû faire, durant ce projet, l’élaboration de mon calendrier a été sûrement ce qui m’a le plus posé de difficultés. En effet n’ayant ni connaissance en javascript à  l’époque (et n’ayant pas connaissance des datepicker déjà  codés) ni la possibilité (les consignes, tout ça) d’utiliser ce genre de script, j’avais recodé un calendrier/datepicker.
Le jour où j’ai découvert qu’écrire le code suivant suffisait, j’ai pleuré :
[cc lang=”php”]$debutCal = new DateTime("last monday of previous month");
$finCal = new DateTime("last day of this month");
if($finCal->format("D") !=="Sunday"){
$finCal->modify("first Sunday of next month");
}
$iterateur = new DatePeriod($debutCal,new DateInterval(‘P1D’),$finCal);
foreach($iterateur as $date){
mettreEnFormeMaDate($date);//selon le design…
}
[/cc]

Un des autres avantages est clairement l’interopérabilité des types. Entre DateTime de MySQL et celui de PHP, il n’y a pas besoin d’adaptation alors qu’il faut passer par strtotime pour avoir un timestamp.
Un des utilisateurs de StackOverflow me donnait justement une réponse tout à  fait détaillée à  propos des exigences auxquelles il avait affaire dans des communication entre php et .NET :

I mentioned before about interop between our PHP systems and .NET systems. Whilst there are no specific issues caused by using a timestamp it’s simply not the practical solution, as again, we use a database that returns a DateTime value which can be sent straight down the pipe. If we were to convert this to a unix timestamp for use internally in PHP we’d also have to then convert it back out if we were to send a response, or send a response to the .NET Application (or should I just say API in this case) that is a timestamp, and convert it at the end. By using DateTime across the board, it alleviates the need for any conversions to happen whatsoever and the whole development process is easier.

S’il est vrai que je suis très favorable aux objets complexes du type DateTime, j’arrive néanmoins à trouver encore des petites utilisations au timestamp :
-marquer temporellement la création d’un fichier/d’un commentaire pour faire des ancres de liens
-simple système affichage/transfert de date

Néanmoins la limite supérieur de dynamique qui est placée à  2038 est vraiment handicapante. Il est aussi à  noter que contrairement à  ce qui est souvent dit, le timestamp est un entier signé (ce qui explique les 68 ans de dynamique (environ 2 000 000 000 de secondes) avancés le plus souvent. En fait on peut aller encore 68 ans en arrière en prenant des timestamp négatifs :
[cc lang=”php”]
echo date(‘d/m/Y’,-1);//prints 31/12/1969
[/cc]