50 ans d’UNIX

Tout est parti d’un post de Stéphane Bortzmeyer sur les 50 ans d’UNIX, ou plutôt de son epoch. Stéphane est quelqu’un de très connu dans la communauté du libre et en général, ce qu’il écrit est non seulement très intéressant mais plus que fiable. Mais là, sur le coup, j’ai eu un doute soudain.

1577836800

L’epoch d’UNIX démarre au 1ᵉʳ janvier 1970 et s’incrémente de 1 chaque seconde. En gros, c’est le nombre de seconde depuis ce premier janvier là. Ainsi, pour les 50 ans d’UNIX, le 1ᵉʳ janvier 2020, l’epoch valait 1577836800 secondes.

# date --date='@0'
jeudi 1 janvier 1970, 01:00:00 (UTC+0100)

# date --date='@1577836800'
mercredi 1 janvier 2020, 01:00:00 (UTC+0100)

Les jours commencent normalement à 0 h pile mais étant sur l’heure de Paris, nous avons une heure de décalage par rapport au temps UTC. En effet, le calcul interne du temps d’une machine UNIX se fait toujours en GMT (Greenwich) contrairement au système Windows de Microsoft qui utilisait en interne le temps local (je ne sais pas ce qu’il advient sur les dernières versions).

Comment arrive-t-on à ce nombre-là ?

Il suffit de faire sur votre calculette ou dans votre terminal Bash le petit calcul suivant :

# echo $(( 3600 * 24 * ( 50 * 365 + 12 ) ))
1577836800

Pour les perdus en Math, on détaille un peu ! Dans un jour, il y a 24 h de 3600 s chacune. On multiplie ce nombre par le nombre d’année et de jour dans l’année soit 50 fois 365. Mais, il ne faut pas oublier qu’il y a des années bissextiles dans lesquelles il y a 1 jour de plus. Vous pouvez refaire le calcul pour montrer qu’il y en a 12 sur cette période (la partie entière de 50/4 donne le bon résultat dans le cas présent).

Rien ne vous choque ?

Si non, passez votre chemin ! Si oui, vous pouvez prolonger la lecture de quelques minutes supplémentaires…

Sur le coup, je me suis dit qu’il n’y a que très peu de chance que le nombre total de seconde entre ces deux premiers janviers finisse par un nombre multiple de 100 (finissant par un double zéro), même si dans la formule nous multiplions par 3600 donc par 100 ! Pourquoi donc ?

Les secondes intercalaires…

Qu’est-ce que c’est que ça ? La seconde intercalaire permet d’ajuster de temps en temps, pas souvent, d’une seconde le temps universel coordonné (UTC) lié au temps atomique international (TAI) afin que ce temps demeure proche du temps universel (UT1) lié à la rotation de la Terre (lentement variable). Eh oui, un jour très lointain, la Terre ne tournera plus sur elle-même.

En bref, on ajoute parfois une seconde ici ou là. Il y a donc des minutes qui durent 61 s et non 60 s. Il est très peu probable d’avoir ajouté 100 s en 50 ans. Effectivement, ce n’est pas le cas.

Comme la commande «date» d’UNIX ne me permet pas de faire un calcul précis du temps, je vais utiliser un petit programme en Perl ayant l’excellente bibliothèque DateTime qui intègre la gestion des secondes intercalaires.

Voici un petit bout de code qu’on peut écrire dans le fichier «date-unix-50years».

#!/usr/bin/perl

use strict;
use DateTime;

my $dt1970 = DateTime->from_epoch(epoch => 0,
   time_zone   => 'Europe/Paris');
my $dt2020 = DateTime->new(
   year        => 2020,
   month       => 01,
   day         => 01,
   hour        => 01,
   minute      => 00,
   second      => 00,
   time_zone   => 'Europe/Paris');

printf "%7i: %10i s\n", 1970, $dt1970->epoch;
printf "%7i: %10i s\n", 2020, $dt2020->epoch;

my $duration = $dt2020->subtract_datetime_absolute($dt1970);
my ($seconds) = $duration->in_units('seconds');

printf "%7s: %10i s\n", 'Elapsed', $seconds;
printf "%7s: %10i s\n", 'Leap', $dt2020->leap_seconds();

On lance le code et voici ce qu’il nous retourne :

# ./date-unix-50years
   1970:          0 s
   2020: 1577836800 s
Elapsed: 1577836827 s
   Leap:         27 s

On retrouve bien les résultats précédents sur les temps epoch. Cela nous arrange quelque part, nous ne sommes pas en train de faire n’importe quoi ! Nous avons utilisé la méthode «subtract_datetime_absolute» qui prend en compte correctement le temps absolu. Par ailleurs, la méthode «leap_seconds» retourne le nombre de secondes intercalaires d’une date donnée.

Il y a donc 1577836827 secondes entre ces deux dates distantes de 50 ans, soit 27 s de plus que ce que nous donnait un bête calcul. Afin de valider tout cela, voici le tableau donnant les secondes intercalaires depuis leur création en 1972. Il y a bien eu 27 secondes ajoutées ces dernières 50 années. Mine de rien, ce n’est pas complètement nul !

Tableau des secondes intercalaires entre 1972 et 2019

Année30 juin
23:59:60
31 déc.
23:59:60
 Année30 juin
23:59:60
31 déc.
23:59:60
197211199710
197301199801
197401199900
197501200000
197601200100
197701200200
197801200300
197901200400
198000200501
198110200600
198210200700
198310200801
198400200900
198510201000
198600201100
198701201210
198800201300
198901201400
199001201510
199100201601
199210201601
199310201700
199410201800
199501201900
199600

On est en droit de se demander pourquoi il y en a de moins en moins depuis les années 2000 ? Mais cela est une autre histoire…

Alors pourquoi l’epoch des systèmes UNIX ne gèrent pas les secondes intercalaires ? Cela est en partie dû à la norme POSIX qui n’est pas cohérente sur le temps. En effet, POSIX exige à la fois des jours durant exactement 86400 s et des dates représentant le temps UTC. Les deux étant incompatibles, il est donc impossible de représenter correctement le temps légal et d’être POSIX. Le choix de respecter une durée journalière en nombre de seconde est (était) le plus simple, le plus rapide et limite le risque de bogue, mais à quelques inconvénients… En pratique, les machines UNIX rattrapent petit à petit cette seconde avant ou après la seconde intercalaire en se synchronisant automatiquement avec des serveurs de temps gérant le protocole NTP. À noter que depuis Windows 10, Microsoft a intégré la gestion des secondes intercalaires au cœur de son système d’exploitation.

Ce contenu a été publié dans Uncategorized, avec comme mot(s)-clé(s) . Vous pouvez le mettre en favoris avec ce permalien.