dimanche 5 septembre 2010

Attention à l'heure d'été en programmation

J'ai observé quelque chose d'intrigant en manipulant un timestamp PHP qui tenait compte de l'heure d'été. C'est un peu une exception car les chances sont minces que vous la rencontriez mais ça vaut la peine de la connaître et d'en comprendre le fonctionnement.

Le 14 mars 2010, l'heure d'été entrait en fonction à 2h du matin. Nous devions tous avancer l'horloge d'une heure. En théorie, personne ne peut prétendre qu'il s'est levé pour aller aux toilettes à 2h30 am et ça peut écourter votre party si vous comptiez sur la fermeture des bars à 3h du matin (en revanche, vous en ressortirez gagnant lorsqu'il faudra reculer l'heure au mois de novembre car vous aurez droit à 2 last calls!).

Disons qu'on crée par programmation un timestamp en date du 13 mars 2010 et qu'on le fait progresser en boucle d'une heure à chaque fois, on pourra remarquer qu'à 2h du matin, le saut se fait automatiquement à 3h (ce qui n'est pas le cas avec une montre analogique).
$timestamp = mktime(22,0,0,3,13,2010); // 22h, le 13 mars 2010

$hour = 60*60; // 1 heure
foreach( range(1,24) as $h ){
echo strftime("%A, %d %B %Y %H:%m", $timestamp) . "\n";
echo "Heure d'été: " . date('I', $timestamp) . "\n";

$timestamp += $hour;
}
Mais qu'est-ce qui arrive si on change le timestamp initial pour 23h30 et qu'on procède avec des sauts d'une journée ?
$timestamp = mktime(23,30,0,3,1,2010); // 23h30, le 1er mars 2010

$day = 60*60*24; // 1 jour
foreach(range(1,31) as $i) {
echo strftime("%A, %d %B %Y", $timestamp) . "\n";
echo "Heure d'été: " . date('I', $timestamp) . "\n";

$timestamp += $day;
}
Exécutez le script pour constater que le 14 mars 2010 n'existe plus. Pourquoi ? Tout simplement parce qu'en ajoutant une journée à la date du 13 mars, 23h30, on obtient le 14 mars 23h30. L'heure d'été devant être en fonction à 2h du matin, le système ajoute une heure au résultat, ce qui nous mène au 15 mars, minuit et 30. Mais ça ne se serait jamais produit si l'heure de base utilisée dans le calcul avait été minuit plutôt que 23h30.

4 commentaires:

  1. c'est pour ca qu'on utilise strtotime() et jamais 24*60*60 ( ou autre :) ajout de secondes


    ajouter une journée : strtotime('+1 day', time() );


    de plus le changement cette année est le 28 donc dans ton exemple c'est le 28 qui devrait sauter pas le 14.

    En tout cas ravi de voir que je suis pas le seul a subir le changement d'heure :)

    RépondreEffacer
  2. @PERRIER L'exemple fonctionne parfaitement même si on utilise le calcul en secondes (le nombre de secondes dans une journée est constant) si et seulement si on veut faire l'ajout de 24 heures sur un timestamp et non sur une date.

    Tu oublies aussi que ce blogue est publié à partir du Québec! La date pour le changement d'heure en Amérique était bel et bien le 14 mars alors qu'en Europe, c'est le 28. Voir Daylight saving time.

    RépondreEffacer
  3. Merci beaucoup pour votre post, il me rassure énormément ! Aussi fou que cela puisse paraitre, je me suis trouvé exactement dans cette situation, et j'avoue que voir mon programme se casser la figure parce que tout d'un coup toute une journée se volatilise, ce n'est pas agréable du tout ! ^^
    Encore merci ! =)

    RépondreEffacer