Alexandre CANTIN - Blog personnel

01 avr. 2020

Les temps relatifs avec Intl.RelativeTimeFormat()

Introduite dans Chrome 71, la classe Intl.RelativeTimeFormat propose un formateur de temps relatif (il y a X secondes, dans X minutes, hier, maintenant…). Offrant un texte plus convivial,  cette mécanique fut utilisée et popularisée par Facebook dans les commentaires et publications de ses utilisateurs. Jusqu’ici, il était nécessaire d’utiliser des librairies tierces comme Moment.js ou date-fns, impactant le poids de notre page.

Utilisation par défaut

Pour utiliser Intl.RelativeTimeFormat, on débute par créer une nouvelle instance de la classe en indiquant la langue (ou la locale) voulue : fr pour le français, en pour l’anglais, es pour l’espagnol etc…

const rtf = new Intl.RelativeTimeFormat("fr");

Nous pouvons ensuite utilisé la méthode format en indiquant la valeur numérique et l’unité de temps parmi second, minut, hour, day, week,month, quarter ou year

Nous obtenons donc :

const rtf = new Intl.RelativeTimeFormat("fr");

rtf.format(0, "second"); // "dans 0 seconde"
rtf.format(-0, "second"); // "il y a 0 seconde"
rtf.format(-2, "hour"); // "il y a 2 heures"
rtf.format(-1, "day"); // "il y a 1 jour"
rtf.format(1, "day"); // "dans 1 jour"
rtf.format(2, "week"); // "dans 2 semaines"
rtf.format(-3, "month"); // "il y a 3 mois"
rtf.format(1, "quarter"); // "dans 1 trimestre"
rtf.format(1, "year"); // "dans 1 an"
rtf.format(-1, "year"); // "il y a 1 an"

Comme on peut le remarquer le texte alterne entre ‘il y a’ et ‘dans’ en fonction du caractère négatif ou positif de la valeur numérique en entrée. Toutefois, le rendu s’avère très générique et peu convivial au final… Peut-on mieux faire ? Absolument !

Personnalisation du formatage

La classe Intl.RelativeTimeFormat accueille un second paramètre dans son constructeur sous forme d’un objet JavaScript: il s’agit d’options de personnalisation. Attardons-nous sur deux d’entre elles.

1- L’option numeric

L’option numeric accepte deux valeurs : always (par défaut) et auto. Elle permet de modifier les conditions d’affichage du nombre en entrée. L’option par défaut, always, force l’apparition de la valeur numérique et c’est pour cette raison que nos exemples précédents alternent seulement entre ‘il y a’ et ‘dans’. En utilisant auto, nous obtenons un formatage plus convivial et comparable à celui de Facebook :

const rtf = new Intl.RelativeTimeFormat("fr", { numeric: "auto" });

rtf.format(0, "second"); // "maintenant"
rtf.format(-0, "second"); // "maintenant"
rtf.format(-2, "hour"); // "il y a 2 heures"
rtf.format(-2, "hour"); // "hier"
rtf.format(1, "day"); // "demain"
rtf.format(2, "week"); // "dans 2 semaines"
rtf.format(-3, "month"); // "il y a 3 mois"
rtf.format(1, "quarter"); // "le trimestre prochain"
rtf.format(1, "year"); // "l’année prochaine"
rtf.format(-1, "year"); // "l’année dernière"

Le verdict reste sans appel : les textes se veulent plus sympathiques qu’auparavant ! D’ailleurs, j’ignore la raison pour laquelle auto n’est pas la valeur par défaut…

2 - L’option style

L’option style impacte la longueur globale de la phrase. Par défaut, long renvoie le texte sans effort de raccourcissement. Les deux autres possibilités  short et narrow abrègent le rendu, à des échelles variables :

const rtf = new Intl.RelativeTimeFormat("fr", { style: "short" });

rtf.format(0, "second"); // "dans 0 s"
rtf.format(-0, "second"); // "il y a 0 s"
rtf.format(-2, "hour"); // "il y a 2 h"
rtf.format(-2, "hour"); // "il y a 2 h"
rtf.format(1, "day"); // "dans 1 j"
rtf.format(2, "week"); // "dans 2 sem."
rtf.format(2, "week"); // "dans 2 sem."
rtf.format(2, "minute"); // "dans 2 min"
rtf.format(-3, "month"); // "il y a 3 m."
rtf.format(1, "quarter"); // "dans 1 trim."
rtf.format(1, "year"); // "dans 1 a"
rtf.format(-1, "year"); // "il y a 1 a"

const rtf2 = new Intl.RelativeTimeFormat("fr", { style: "narrow" });

rtf2.format(0, "second"); // "+0 s"
rtf2.format(-0, "second"); // "-0 s"
rtf2.format(-2, "hour"); // "-2 h"
rtf2.format(-2, "hour"); // "-2 h"
rtf2.format(1, "day"); // "+1 j"
rtf2.format(2, "week"); // "+2 sem."
rtf2.format(2, "week"); // "+2 sem."
rtf2.format(2, "minute"); // "+2 min"
rtf2.format(-3, "month"); // "-3 m."
rtf2.format(1, "quarter"); // "+1 trim."
rtf2.format(1, "year"); // "+1 a"
rtf2.format(-1, "year"); // "-1 a"

Quid de la compatibilité…

Comme toutes nouvelles fonctionnalités, la question de sa compatibilité se pose. Cette dernière n’est pas encore totale et il faudra certainement attendre quelques mois/années pour une prise en charge totale :

Supportés : Chrome - Firefox et Opéra. Non supportés: Edge, Internet Explorer et Safari

Conclusion

Bien qu’encore mal supporté Intl.RelativeTimeFormat reste prometteur pour créer des dates relatives sans librairie tierce.

On peut toutefois regretter que cette classe ne propose pas de mise à jour automatique du texte en fonction d’une date en entrée, un comportement qu’il nous faudra recréer soi-même pour le moment. Espérons toutefois que cette modification viendra un jour !

Pour aller plus loin :

https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Objets_globaux/Intl.RelativeTimeFormat

https://developers.google.com/web/updates/2018/10/intl-relativetimeformat