logo Pierre AULAS
Les dates en php - Pierre Aulas
 Parcours  |   Réalisations  |   Cours  |   Chroniques  |   Divers
Le temps Unix
date()
getDate()
Exercices
Solutions

Les dates

1. Au commencement était UNIX

S'il vous prend l'idée d'utiliser la fonction date() sans argument, php vous renverra la date en format dit "epoch UNIX".

Ce nombre correspond au nombre de secondes écoulées depuis le 1er janvier 1970 à minuit GMT. Pour les machines c'est très commode puisque cela leur permet de calculer facilement les différences entre deux dates sans avoir à prendre en compte les différents calendriers existants et leurs spécificités (heure d'été et d'hiver, mois avec un nombre de jours variables, années bissextiles pour ne parler que de notre calendrier).
Une donnée de 32 bytes ne permet de coder - en secondes - que l'équivalent de 68 ans. Il y aurait donc un effet "an 2000" possible en 2038. Sauf que d'ici-là il est probable que les machines n'auront plus rien à voir avec celles que nous connaissons.

La seule limite du système actuel est la gestion des dates placées longtemps "avant UNIX". Méfiez-vous si vos projets présentent des aspects "historiques".

Haut de page

2. La fonction date()

Pour des raisons d'humanité évidente, php dispose d'une fonction qui traduit le format epoch UNIX et lui donne toutes les formes que l'on peut souhaiter :

date (nv_format, date_format_UNIX).

Exemples :

  print date ("d-m-y"); //Renvoi la date courante de la machine sous la forme "12-10-06"
  print date ("d/m/y", 1172575871); //Renvoi la date correspondante à la 172575871ème seconde écoulée depuis 1970 soit "27/02/07"

Les seules choses à connaître sont les spécificateurs de date du tableau ci-dessous.
Inutile de les connaître par cœur : retenez seulement que chaque type de date est désigné par la première lettre du terme anglais équivalent :
  - d pour day donc jour.
  - m pour month donc mois.
  - y pour year donc année.
  - h pour hour donc heure.
  - i pour …minute : c'est la seule exeception puisque le m est pris par les mois.
  - s pour second donc seconde.
Il ne vous reste plus qu'à savoir que la présentation change légérement selon que vous écrivez votre lettre en majuscule ou en minuscule.

Tableau des spécificateurs de date
Opérateur  Description  Exemple
d Jour du mois (avec un zéro initial)  01 à 31
D Jour de la semaine, en trois lettres  Mon à Sun
l Jour de la semaine en toutes lettres  Monday à Sunday
j Jour du mois sans les zéros initiaux  1 à 31
w Jour de la semaine au format numérique  0 (dimanche) à 6
z Jour de l'année  0 à 365
W Numéro de semaine dans l'année  0 à 52
m Mois avec zéros initiaux  01 à 12
M Mois, en trois lettres  Jan à Dec
F Mois en toutes lettres  January à December
n Mois sans les zéros initiaux  1 à 12
t Nombre de jours dans le mois  28 à 31
L Bissextile  1 si oui, 0 si non
Y Année sur 4 chiffres  1999
y Année sur 2 chiffres  99
g Format 12h, sans les zéros initiaux  1 à 12
G Format 24h, sans les zéros initiaux  0 à 23
h Format 12h, avec les zéros initiaux  01 à 12
H Format 24h, avec les zéros initiaux  00 à 23
i Minutes avec les zéros initiaux  00 à 59
s Secondes, avec zéros initiaux  00 à 59
I (i maj)  L'heure d'été est activée ou pas  1 si oui, 0 si non
O  Différence avec Greenwich  +0200
Haut de page

3. La fonction getDate()

Tout cela c'est très bien si vous êtes anglophone. Mais si vous faites parti des 95% de la population mondiale dont la langue maternelle n'est pas l'anglais, vous allez devoir manipuler les jours, les semaines et les mois afin de les traduire dans votre langue.

Pour y parvenir, vous disposez de la fonction getDate() à laquelle on passe une date en format Unix et qui renvoie un tableau associatif contenant les informations décrites dans le tableau qui suit :

Tableau associatif renvoyé par getDate()
Clef  Contenu  Exemple
seconds  Représentation numérique des secondes  0 à 59
minutes  Représentation numérique des minutes  0 à 59
hours  Représentation numérique des heures  0 à 23
mday  Représentation numérique du jour du mois courant  1 à 31
wday  Représentation numérique du jour de la semaine courante  0 (pour Dimanche) à 6 (pour Samedi)
mon  Représentation numérique du mois  1 à 12
year  Année, sur 4 chiffres  Exemples : 1999 ou 2003
yday  Représentation numérique du jour de l'année  0 à 365
weekday  Version texte du jour de la semaine  Sunday à Saturday
month  Version texte du mois, comme January ou March January à December
0  Nombre de secondes depuis l'époque Unix, similaire à la valeur retournée par la fonction time() et utilisée par date().  Dépend du système, typiquement de -2147483648 à 2147483647.

Autrement dit si vous faites :

$date = getDate(time());

// $date contient alors quelque chose du genre: Array ( [seconds] => 23 [minutes] => 54 [hours] => 11 [mday] => 17 [wday] => 4 [mon] => 4 [year] => 2008 [yday] => 107 [weekday] => Thursday [month] => April [0] => 1208426063 )

print $date['mday']."/".$date['mon']."/".$date['year'];

// Ce qui renvoie "17/4/2008"

Haut de page

Exercices

Exercice 1 - What time is it ?

Commençons par mettre en œuvre les questions d'affichage.

Pour cela le plus simple est d'utiliser la fonction time() qui vous renvoie l'heure et la date de votre machine.
Il existe également un argument timestamp que l'on peut passer en second argument à la fonction date() qui permet de récupérer l'heure et la date de votre machine.

1. Afficher la date actuelle à la façon machine (il s'agit d'un 12 avril) :

4-12-08 (vous êtes prié de respecter la ponctuation)

2. Afficher la date actuelle à la façon anglo-saxonne :

April 12, 2008. (vous êtes prié de respecter la ponctuation)

3. Afficher la date au format français :

12 avril 2008

Comme cela va vous resservir tout le temps, créez vous une fonction qui convertit les noms de mois anglais en nom de mois français, et faîtes de même pour les jours de la semaine.

4. Afficher la date au format français pénible :

Mardi 12 avril 2008

Solution

Haut de page

Exercice 2 - en chiffre romain ?

Pas de chance, votre client est un psycho-rigide qui se prend pour César-Auguste : il exige que les dates de ses courriers soient écrites en chiffre romain (il a vu cela dans un film consacré à Napoléon), dans le genre :

Mardi XII avril MMVIII

À vous de faire la fonction qui permet de transformer le chiffre 12 en XII. Réflechissez un peu au problème. On peut lui trouver plusieurs solutions, à l'élégance et à l'efficacité variable.

Solution

Haut de page

Solutions

Exercice 1 - What time is it ?

1. Afficher la date actuelle à la façon machine (il s'agit d'un 12 avril) :

4-12-08 (vous êtes prié de respecter la ponctuation)

print date("m-d-y",time());

Sauf que si vous écrivez la ligne qui précéde, il y a fort à parier que vous vous retrouvez avec un 0 devant le numéro du mois ou du jour, ce qui visuellement n'est pas toujours du meilleur effet. Il faut donc leur préférer les lettres j et n qui renvoient respectivement au numéro du jour et au numéro du mois sans le zéro devant.

print date("n-j-y",time());

2. Afficher la date actuelle à la façon anglo-saxonne :

April 12, 2008.

print date("F d, Y.",time());

3. Afficher la date au format français :

12 avril 2008

Là c'est un peu plus dur. Il faut dans un premier temps avoir recours à la fonction getDate() pour pouvoir manipuler les différents éléments composant la date (le jour, le mois, l'année) séparement.

$date = getDate(time());

Pour rappel, vous pouvez voir ce que $date a dans le ventre à l'aide d'un print_r($date);, lequel vous renverra quelque chose du genre :

Array ( [seconds] => 23 [minutes] => 54 [hours] => 11 [mday] => 17 [wday] => 4 [mon] => 4 [year] => 2008 [yday] => 107 [weekday] => Thursday [month] => April [0] => 1208426063 )

Comme il s'agit de présenter votre date en affichant le nom du mois en français, il faut disposer d'une petite fonction dans le genre de celle décrite ci-après :

function MoisFrancais($pMois)
{
$aMois = array(  
    "Janvier",
    "Février",
    "Mars",
    "Avril",
    "Mai",
    "Juin",
    "Juillet",
    "Août",
    "Septembre",
    "Octobre",
    "Novembre",
    "Décembre"
    );
if($pMois < count($aMois)+1)
    return $aMois[$pMois-1] ;
}

Il ne vous reste plus qu'à appeler votre belle fonction et afficher le résultat :

print $date['mday']." ".MoisFrancais($date['mon'])." ".$date['year'];

4. Afficher la date au format français pénible :

Mardi 12 avril 2008

Ce coup-ci vous allez devoir écrire une petite fonction dans le même genre que la précédente mais pour gérer l'affichage des jours en français :

function JourFrancais($pJour)
{
  $aJour = array(  
    "Lundi",
    "Mardi",
    "Mercredi",
    "Jeudi",
    "Vendredi",
    "Samedi",
    "Dimanche"
    );
  if($pJour < count($aJour)+1)
    return $aJour[$pJour-1];
}

Et du coup l'affichage souhaité nécessite un appel à votre belle fonction :

print JourFrancais($date['mday'])." ".$date['mday']." ".MoisFrancais($date['mon'])." ".$date['year'];

Haut de page

Exercice 2 - en chiffre romain ?

Bon, si vous avez réussi à monter un algorithme qui fonctionne à peu près, vous avez droit à toute notre estime.

Mardi XII avril MMVIII

Nous proposons trois solutions, de la plus discutable à la plus "performante". Cela pour montrer qu'il n'y a de solution unique en informatique mais qu'il y a des algorithmes plus performants que d'autres.

Première solution

C'est la solution la plus intuitive, qui suit l'ordre de la réflexion.

function ChiffreRomain($nombre_arab){
  $nb_b10=array('I','X','C','M');
  $nb_b5=array('V','L','D');
  $nbrom='';
  $nombre=$nombre_arab;
  if($nombre>=0 && $nombre<4000){ // on peut convertir  
    for($i=3; $i>=0 ; $i--){
      $chiffre=floor($nombre/pow(10,$i));
      if($chiffre>=1){
        $nombre=$nombre-$chiffre*pow(10,$i);
        if($chiffre<=3){
          for($j=$chiffre; $j>=1; $j--){
          $nbrom=$nbrom.$nb_b10[$i];
          }
        }
        elseif($chiffre==9){
          $nbrom=$nbrom.$nb_b10[$i].$nb_b10[$i+1];
        }
        elseif($chiffre==4){
          $nbrom=$nbrom.$nb_b10[$i].$nb_b5[$i];
        }
        else{
          $nbrom=$nbrom.$nb_b5[$i];
          for($j=$chiffre-5; $j>=1; $j--){
            $nbrom=$nbrom.$nb_b10[$i];
          }
        }
      }
    }
  }
  else{
    echo 'Valeur Hors Limite';
  }
  return $nbrom;
}

Deuxième solution

Cette solution surprend davantage. Elle repose essentiellement sur la fonction str_replace qui permet de faire des remplacements de caractères. On commence par diviser le nombre passé en paramètre en unités, dizaines, centaines, milliers puis on les convertis en autant de lettres que nécessaire correspondant à cette unité puis on fait un remplacement de caractère pour gérer les cas: "IV", "V", "IX", "XL", etc.

function ChiffreRomain($nombre)
{
  $nombre = (int) $nombre;
  if($nombre > 0 && $nombre<5000)
  { // Le nombre doit être un entier positif
      $resultat = "";
    $romain = array(1000=>"M",100=>"C",10=>"X",1=>"I");
    foreach($romain as $valeur=>$caractere)
    {
      $nbe = (int) ($nombre / $valeur); // On divise par 1000, puis par 100, puis par 10, puis par 1
      for($i=0;$i<$nbe;$i++)
      {
      // On ajoute $nbe fois la lettre
        $resultat .= $caractere;
      }
      $nombre -= ($nbe*$valeur);
    }
    // Conversion des cas particuliers
    $resultat = str_replace(array("CCCCCCCCC","CCCCC","CCCC","XXXXXXXXX","XXXXX","XXXX","IIIIIIIII","IIIII","IIII"),
                            array("CM","D","CD","XC","L","XL","IX","V","IV"),$resultat);
  }
  else
  {
    $resultat = "NaN"; // On ne peut pas convertir un nombre <= 0
  }
  return $resultat;
}

Troisième solution

Bon, cette dernière solution n'est pas intuitive mais plus élégante et portable (on peut la réutiliser facilement pour d'autres types d'écritures en modifier le tableau associatif qui débute la fonction). Je vous laisse le découvrir le merveilleux mécanisme de ladite fonction.

function ChiffreRomain($pDecimal)
{
  $convertisseur=array(
    1 => "I",
    4 => "IV",
    5 => "V",
    9 => "IX",
    10 => "X",
    40 => "XL",
    50 => "L",
    90 => "XC",
    100 => "C",
    400 => "CD",
    500 => "D",
    900 => "CM",
    1000 => "M"
    );
  krsort($convertisseur); // On range dans l'ordre inverse
  $resultat="";
  foreach($convertisseur as $clef => $valeur)
  {
  // Tant que le chiffre est supérieur à la clef (1000, puis 900, 500 etc.),
  // on garde son équivalent romain en mémoire et on le diminue du montant de la clef.
    while($pDecimal>=$clef)
    {
      $resultat.=$valeur;
      $pDecimal-=$clef;
    }
  }
  return $resultat;
}

Ne pas oublier : la mise en pratique de ces belles fonctions.

$date = getDate(time());
print JourFrancais($date['wday'])." ".ChiffreRomain($date['mday'])." ".MoisFrancais($date['mon'])." ".ChiffreRomain($date['year']);

Haut de page
Plan du site  |  Mentions légales  |  Crédits  |  Aide