Formater des dates avec légèreté

Il existe de très nombreuses solutions pour formater des dates. Certaines utilisent explode() pour séparer les entrées, d'autres utilisent preg_match() et tout cela fini bien souvent par un appel à date() et la modification à la main du nom des mois et des jours pour localiser tout ça. Je ne compte plus le nombre de ses mauvais exemples. Après tout j'ai fais bêtement pareil pendant longtemps.

La première chose à faire est donc de fuir comme la peste la commande date(). Elle n'est pas localisée et demande beaucoup trop d'effort pour être utile. Nous allons plutôt jouer gentiment avec les fonctions : setlocale(), strtotime() et strftime().

3 fonctions pour un plaisir immédiat

setlocale

setlocale() permet de modifier les options de localisation, comme – entre autre – le format de date et d'heure utilisé par strftime(). En utilisant cette commande vous pouvez basculer tout l'environnement dans la langue que vous souhaitez ou simplement quelques parties. Par exemple, LC_TIME suffit amplement pour localiser strftime().

Par contre, la valeur de la langue à utiliser est un mystère cosmique. Faites une recherche et vous trouverez une dizaine de conseils, tous aussi merveilleux que différents, sur la bonne valeur à utiliser. Si l'on s'en réfère à la documentation, fr_FR devrait faire l'affaire. Si l'on s'en réfère à la norme ISO, fr, fra ou bien fre devrait aussi faire l'affaire. Hmpf — de mon expérience, et après bien des serveurs, une valeur qui marche à coup sûr est french.

<?php

setlocale(LC_TIME, 'french');

strtotime

strtotime() est une bénédiction, surtout lorsque l'on pense au calvaire qu'a été la manipulation de date avec date(). En effet, non seulement elle prend en charge de nombreux formats de date sans broncher, elle permet également de manipuler les dates avec une facilité appréciée :

<?php

echo strtotime("now")"\n";
echo strtotime("10 September 2000")"\n";
echo strtotime("+1 day")"\n";
echo strtotime("+1 week")"\n";
echo strtotime("+1 week 2 days 4 hours 2 seconds")"\n";
echo strtotime("next Thursday")"\n";
echo strtotime("last Monday")"\n";

Difficile de faire plus simple !

strftime

strftime() retourne la date sous la forme d'une chaîne formatée, en utilisant une date spécifiée ou la date actuelle. De nombreuses options sont disponibles pour la mise en forme de la date. Voici une petite liste à garder sous le coude :

  • Année
    • %Y – année sur quatre chiffres
    • %y – année sur deux chiffres (de 00 à 99)
  • Mois
    • %B – nom complet du mois (localisé)
    • %b – nom abrégé du mois (localisé)
    • %m – mois en numérique (intervalle 1 à 12)
  • Jour
    • %A – nom complet du jour de la semaine (localisé)
    • %a – nom abrégé du jour de la semaine (localisé)
    • %d – jour du mois en numérique (intervalle 01 à 31)
    • %j – jour de l'année, en numérique (intervalle 001 à 366)
  • Heure
    • %H – heure de la journée en numérique, et sur 24-heures (intervalle de 00 à 23)
    • %M – minute en numérique
    • %S – secondes en numérique

Une classe pour un confort durable

Je vous propose maintenant une petite classe qui se chargera de gérer tout ça en transparence, qui prendra soin des capitales des jours et des mois – si ça vous chante – et renverra une jolie chaîne en UTF-8 parce que l'ISO ça pue.

<?php

class WdDateTime
{
    var $time;

    function WdDateTime($date='now')
    {
        $this->time = strtotime($date);
    }
    
    function modify($relative)
    {
        $this->time = strtotime($relative$this->time);
    }
        
    function format($fmt,$upper=false)
    {
        $date = strftime($fmt$this->time);

        if ($upper)
        {
            $date = preg_replace('#^[[:lower:]]|\s+[[:lower:]]#e''strtoupper("\0")'$date);
        }

        return utf8_encode($date);
    }
}

« Un exemple » me direz-vous ? En voici un prestement :

<?php

setlocale(LC_TIME, 'french');

$time = new WdDateTime('2007-12-08');

echo "Le mois prochain nous serons le : " . $time->format('%A %d %B %Y''+1 month'true) . "<br />";

$time->modify('+10 year');

echo "Dans 10 ans nous serons le : " . $time->format('%A %d %B %Y') . "<br />";
echo "Jours suivants : ";

for ($i = 1 ; $i < 7 ; $i++)
{
    echo " " . $time->format('%A'"+$i day"true);
}

echo "<br />";

Devrait afficher :

Le mois prochain nous serons le : mardi 08 janvier 2008
Dans 10 ans nous serons le : vendredi 08 décembre 2017
Jours suivants : Samedi Dimanche Lundi Mardi Mercredi Jeudi

Petite note de fin

Si vous utilisez une option documentée qui n'est pourtant pas supportée – pour une raison infecte et mystérieuse – vous obtiendrez un résultat nul. Pensez alors à vérifier vos options. Par exemple, l'option %e n'a jamais fonctionné sur aucun des serveurs que j'ai utilisé, pas plus que l'option %T, qui aurait pu être très pratique. Tout cela n'est que broutille. Vous avez maintenant tout ce dont vous avez besoin pour gérer d'une façon honteusement simple vos dates.

À vous les dates sexys et faciles !

3 commentaires

Loutente
Loutente

J'ai un soucis avec les dates. Comme tu le spéccifies beaucoup de personnes utilisent explode. je viens du monde Java et trouve cela un peu sale. Mais pour gérer le fait d'avoir des données en entrée au format français. je bloque un peu.

comme faire proprement pour passer la date '23/02/2010' à ton constructeur sans avoir de problème?

Olivier
Olivier

Malheureusement, point de salut pour les dates en français, il faudra les convertir au format international pour en tirer quelque chose. Comme tu le dis, le plus simple c'est de passer par un explode :

<?php

$date = '23/02/2010';

$parts = explode('/'$date);

$date = sprintf('%04d-%02d-%02'$parts[2]$parts[1]$parts[0]);

var_dump($date) // string '2010-02-23' (length=10)

Si tu veux pas passer par un explode, la fonction strptime() permet de parser une chaine pour obtenir les éléments d'une date, mais la commande n'est pas disponible sous Windows, et finalement on se retrouve avec un tableau plein de valeurs pas plus pratique à gérer….

Ça ressemble à quoi la gestion des dates en français sous Java ?

loutente
loutente

Merci . Java c'est assez simple, on précise le format de la date et c'est tout.

public static Date stringToDate(String sDate, String sFormat) throws Exception { SimpleDateFormat sdf = new SimpleDateFormat(sFormat); return sdf.parse(sDate); }

Laisser un commentaire