Catégories
Astuces et Design

Learn date-fns: une bibliothèque de dates JavaScript légère

Introduction à date-fns

Travailler avec des dates en JavaScript est une douleur. Les méthodes de date natives sont souvent verbeuses et parfois incohérentes – ce qui les rend également sujettes aux erreurs. Mais de bonnes nouvelles sont à portée de main. Il existe plusieurs bibliothèques pour éliminer la douleur de la manipulation. Ces bibliothèques sont aux dates JavaScript, ce que jQuery est à l'API DOM native.

Laisse moi te donner un exemple. Voici la réponse acceptée à une question de Stack Overflow demandant comment obtenir le dernier jour du mois:

var t = new Date();
alert( new Date(t.getFullYear(), t.getMonth() + 1, 0, 23, 59, 59) );

Bien sûr, cela fonctionne, mais ce n’est pas tout de suite évident ce que les chiffres après getMonth représenter. Maintenant, comparez cela avec le beaucoup plus lisible:

const today = new Date();
console.log( lastDayOfMonth(today) );

Cette lastDayOfMonth est une méthode fournie par date-fns, un ensemble d'outils complet auto-proclamé pour manipuler les dates JavaScript dans le navigateur et Node.js.

Dans cet article, je vais vous montrer comment démarrer avec date-fns. Après l'avoir lu, vous pourrez l'inclure dans vos projets et profiter de ses nombreuses méthodes d'aide pour manipuler facilement les dates. Cela fera du code comme t.getMonth() + 1, 0, 23, 59, 59 chose du passé.

Alors, pourquoi ne pas simplement utiliser Moment.js?

Moment.js est une bibliothèque fantastique pour travailler avec des dates en JavaScript – elle possède de nombreuses fonctionnalités et offre une multitude d'utilitaires utiles. Il n'est cependant pas sans critiques.

Beaucoup de gens citent le fait que les objets Moment sont modifiables (c'est-à-dire des opérations comme add, ou subtract changer l'objet Moment d'origine) car il est déroutant pour les développeurs et source de bogues.

Il a également été critiqué pour sa grande taille. Moment ne fonctionne pas bien avec les algorithmes modernes de «tremblement d'arbres» et si vous avez besoin d'une internationalisation ou d'une prise en charge du fuseau horaire, vous pouvez rapidement vous retrouver avec un ensemble JavaScript assez volumineux.

Cela est allé si loin que les outils de développement de Chrome soulignent désormais le fait que l'utilisation de Moment peut entraîner de mauvaises performances.

Tout cela a conduit les responsables de Moment à placer le projet en mode maintenance et à décourager Moment d'être utilisé dans de nouveaux projets à l'avenir.

Nous reconnaissons que de nombreux projets existants peuvent continuer à utiliser Moment, mais nous aimerions décourager Moment d'être utilisé dans de nouveaux projets à l'avenir. Au lieu de cela, nous aimerions recommander des alternatives qui sont d'excellents choix pour une utilisation dans les applications modernes d'aujourd'hui.

Cela fait de date-fns l'une des meilleures alternatives à Moment.js.

Installation

Depuis la version deux de la bibliothèque, le seul moyen d'installer date-fns est sous forme de package npm.

npm install date-fns

Ou via Yarn:

yarn add date-fns

Vous pouvez utiliser date-fns avec le système de modules CommonJS et également avec les modules ES:


const { lastDayOfMonth } = require('date-fns');

ou:


import { lastDayOfMonth } from 'date-fns';

Il n'y a malheureusement actuellement aucune version CDN de date-fns disponible. Sa suppression et sa possible réintégration sont en cours de discussion dans ce numéro de GitHub. Mais cela ne veut pas dire que vous ne pouvez pas l'utiliser dans un navigateur, mais simplement que vous devrez introduire une étape de regroupement dans votre flux de travail.

Voyons comment faire cela maintenant.

Comment regrouper date-fns pour une utilisation dans un navigateur

Je suppose que vous avez installé Node et npm sur votre ordinateur. Sinon, veuillez consulter notre tutoriel sur l'installation de Node.

Ensuite, installez Parcel. Il s'agit d'un bundler (similaire à Webpack), qui vous permettra de regrouper votre JavaScript et de le servir dans un navigateur.

npm install -g parcel-bundler

Ensuite, créez un nouveau projet avec un package.json fichier.

mkdir date-fns
cd date-fns
npm init -y

Installez la bibliothèque date-fns, comme ci-dessus:

npm install date-fns

Créez maintenant deux fichiers, index.html et index.js.


<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>date-fnstitle>
  head>
  <body>
    <script src="index.js">script>
  body>
html>
import { lastDayOfMonth } from 'date-fns';

const today = new Date();
console.log(lastDayOfMonth(today));

Démarrez le serveur de développement intégré de colis:

parcel index.html

Et accédez à http: // localhost: 1234. Vous ne verrez rien affiché sur la page, mais si vous ouvrez la console du navigateur. vous devriez qu'il a enregistré le dernier jour du mois en cours.

En ce qui concerne le déploiement, vous pouvez exécuter:

parcel build index.js --experimental-scope-hoisting

pour que Parcel produise un bundle minifié et arborescent dans le dist dossier.

Utilisation de base de date-fns

Maintenant que nous sommes opérationnels, voyons ce que date-fns peut faire.

L'une des tâches les plus courantes lorsque vous travaillez avec des dates est la possibilité de les formater correctement. Nous pouvons le faire avec la fonction de format date-fns.

Modifiez le code HTML de notre page d'exemple ci-dessus pour qu'il ressemble à ceci:

<body>
  <h1>The date today is <span>span>h1>
  <script src="index.js">script>
body>

Dans index.js nous voulons importer le format fonction, à laquelle nous pouvons ensuite transmettre la date du jour et une chaîne de format. Nous voulons ensuite afficher le résultat sur la page.

import { format } from 'date-fns';

const today = new Date();
const formattedDate = format(today, 'dd.MM.yyyy');

document.querySelector('h1 > span').textContent = formattedDate;

Bien sûr, nous ne sommes pas limités à un dd.MM.yyyy format, essayons quelque chose de différent:

const formattedDate = format(today, 'PPPP');

Cela formatera la sortie comme ceci: Wednesday, September 16th, 2020. Vous pouvez trouver une liste complète des options de mise en forme dans la documentation.

Modifier les paramètres régionaux

Si vous avez un site Web en plusieurs langues, date-fns simplifie l'internationalisation des heures et des dates. Salutons nos invités allemands:

<h1>Heute ist <span>span>h1>

Et dans le fichier JavaScript, nous pouvons importer la langue allemande et la transmettre au format fonction:

import { format } from 'date-fns';
import { de } from 'date-fns/locale';

const today = new Date();
const formattedDate = format(today, 'PPPP', { locale: de });

document.querySelector('h1 > span').textContent = formattedDate;

Cela produira quelque chose du genre: Heute ist Mittwoch, 16. September 2020.

Cela peut sembler compliqué d'exiger et de passer des locales comme options, mais contrairement à Moment.js qui gonfle votre build avec toutes les locales par défaut, date-fns oblige les développeurs à exiger manuellement les locales au fur et à mesure qu'elles sont nécessaires.

Vous pouvez afficher une liste des paramètres régionaux disponibles en consultant le node_modules/date-fns/locale dossier dans votre projet.

Immuabilité, pureté et simplicité

L'un des arguments de vente de date-fns est que ses fonctions sont pures et simples à expliquer. Cela conduit à un code facile à comprendre, qui est plus facile à déboguer lorsque les choses tournent mal.

Permettez-moi de le démontrer en utilisant Moment.js comme contre-exemple. Comme mentionné précédemment, les dates dans Moment sont modifiables, ce qui peut entraîner un comportement inattendu.

const moment = require('moment');
const now = new Date();
const mNow = moment(now);

mNow.add('day', 3);
console.log(mNow.toDate());
mNow.add(3, 'day');
console.log(mNow.toDate());



Il y a quelques points à noter ici. Des moments add function n'est pas pointilleux sur l'ordre dans lequel elle accepte ses arguments (bien que la première méthode lancera désormais un avertissement de désapprobation). Mais le plus déroutant est que si vous appelez add plusieurs fois de suite, vous n'obtiendrez pas le même résultat car les objets Moment sont mutables:

mNow.add(3, 'day'); 
mNow.add(3, 'day'); 

Maintenant, comparez cela à date-fns qui garde les arguments dans un ordre et retourne toujours le même résultat, renvoyant un nouveau Date objet pour chaque appel.

import { addDays } from 'date-fns';

const today = new Date();
const threeDaysTime = addDays(3, today);
const sixDaysTime = addDays(threeDaysTime, 3);

console.log(today); 
console.log(threeDaysTime); 
console.log(sixDaysTime); 

Notez également à quel point le nom de la méthode est plus expressif (addDays au lieu de juste add), garder les choses cohérentes et avoir une méthode pour faire une chose et une seule chose.

Comparaison des dates

Si vous regardez la liste des articles sur le canal JavaScript de SitePoint, vous pouvez voir que certains sont répertoriés comme étant publiés à une certaine date, tandis que d’autres sont répertoriés comme étant publiés il y a X jours. Cela peut prendre un certain temps si vous essayez d'implémenter cela en JavaScript vanilla, mais avec date-fns, c'est un jeu d'enfant – utilisez simplement la méthode formatDistance.

Comparons deux dates différentes.

import { formatDistance } from 'date-fns';

const startDate = new Date(2020, 8, 16); 
const endDate = new Date(2020, 11, 25); 
const distanceInWords = formatDistance(startDate, endDate);

console.log(`It is ${distanceInWords} until Christmas`);

Remarquez comment, lorsque vous travaillez avec JavaScript, les mois sont basés sur zéro (par exemple, mois 11 = décembre), mais les jours comptent à partir de un. Cela me fait trébucher encore et encore.

Travailler avec des collections de dates

Date-fns a des méthodes d'assistance très pratiques que vous pouvez utiliser pour manipuler des collections de dates de toutes sortes de manières.

Commande d'une collection de dates

L'exemple suivant utilise compareAsc pour trier les dates par ordre croissant. Pour ce faire, il renvoie 1 si la première date est postérieure à la seconde, -1 si la première date est antérieure à la seconde ou 0 si les dates sont égales.

import { compareAsc } from 'date-fns';

const date1 = new Date('2005-01-01');
const date2 = new Date('2010-01-01');
const date3 = new Date('2015-01-01');
const arr = (date3, date1, date2);
const sortedDates = arr.sort(compareAsc);


Comme vous pouvez le voir, les dates sont maintenant dans l'ordre croissant.

La méthode homologue pour compareAsc est compareDesc.

import { compareDesc } from 'date-fns';
...
const sortedDates = arr.sort(compareDesc);

Générer les jours entre deux dates

Pour générer les jours entre deux dates, vous pouvez utiliser la méthode addDays que nous avons rencontrée précédemment, ainsi que l'assistant eachDayOfInterval qui renvoie un tableau de dates dans la plage spécifiée.

import { addDays, eachDayOfInterval } from 'date-fns';

const today = new Date();
const aWeekFromNow = addDays(today, 7);
const thisWeek = eachDayOfInterval(
  { start: today, end: aWeekFromNow },
);

console.log(thisWeek);


Recherche de la date la plus proche

La recherche de la date la plus proche d'une certaine date dans un tableau de dates peut être effectuée à l'aide de la méthode la plus procheTo. Cet extrait de code fait suite à l'exemple précédent:

import { addDays, eachDayOfInterval, closestTo } from 'date-fns';
...
const christmas = new Date(2020, 11, 25);
const closestToChristmasDate = closestTo(christmas, thisWeek);

console.log(closestToChristmasDate);

Il existe également la méthode la plus procheIndexTo si vous souhaitez obtenir l'index du tableau à la place.

Valider une date

La dernière aide que je souhaite examiner est la méthode isValid qui, comme son nom l'indique, vérifie si une date donnée est valide.

Cependant, en raison de la façon dont JavaScript traite les dates, il y a quelques pièges à connaître:

import { isValid } from 'date-fns';

const invalidDate = new Date('2020, 02, 30');
console.log(isValid(invalidDate));

Vous seriez pardonné de penser que l'extrait ci-dessus devrait s'afficher false, car le 30 février 2020 est évidemment une date invalide. Pour comprendre ce qui se passe, entrez new Date('2020, 02, 30') dans la console de votre navigateur. Tu verras Sun Mar 01 2020 revenez à vous – JavaScript a pris le jour supplémentaire de la fin février, et l'a transformé en 1er mars (qui est bien sûr une date valide).

Pour contourner ce problème, nous pouvons analyser la date avant de vérifier sa validité:

import { isValid, parse } from 'date-fns';

const validDate = parse('29.02.2020', 'dd.MM.yyyy', new Date());
const invalidDate = parse('30.02.2020', 'dd.MM.yyyy', new Date());

console.log(validDate);


console.log(invalidDate);


console.log(isValid(validDate));


console.log(isValid(invalidDate));

Cela peut facilement être extrait dans une petite méthode d'aide, utile, par exemple, pour valider l'entrée utilisateur dans les formulaires.

Fuseaux horaires

Un inconvénient de date-fns est qu'il ne dispose actuellement d'aucune fonction d'assistance de fuseau horaire comme Moment.js, mais renvoie plutôt le fuseau horaire local sur lequel le code s'exécute.

Cette réponse Stack Overflow donne des informations sur le niveau de Date les objets ne stockent pas réellement les données du «fuseau horaire réel». Dans ce fil, vous remarquerez qu'ils mentionnent une méthode de définition native des fuseaux horaires en JavaScript. Ce n'est pas une solution complète, mais elle fonctionne pour de nombreux scénarios qui ne nécessitent qu'une conversion de sortie (de l'heure UTC ou locale vers un fuseau horaire spécifique).

new Date().toLocaleString("en-US", {timeZone: "America/New_York"});

Les fuseaux horaires sont en fait un problème compliqué à résoudre, c'est pourquoi MomentJS a une bibliothèque séparée pour cela. Des plans sont en cours pour ajouter la prise en charge du fuseau horaire à date-fns, mais au moment de la rédaction de cet article, ce travail est toujours en cours.

Il existe cependant un package disponible sur npm (basé sur une demande d'extraction non fusionnée vers date-fns) qui ajoute la prise en charge du fuseau horaire pour date-fns v2.0.0 à l'aide de l'API Intl. Avec 140 000 téléchargements hebdomadaires, il semble populaire, mais au moment de la rédaction de cet article, il n'a pas été mis à jour depuis plusieurs mois.

Cela dit, voici comment vous pouvez l'utiliser:

npm i date-fns-tz
import { format, utcToZonedTime } from 'date-fns-tz';

const today = new Date(); 
const timeZone = 'Australia/Brisbane'; 
const timeInBrisbane = utcToZonedTime(today, timeZone);

console.log(`
  Time in Munich: ${format(today, 'yyyy-MM-dd HH:mm:ss')}
  Time in Brisbane: ${format(timeInBrisbane, 'yyyy-MM-dd HH:mm:ss')}
`);



Conclusion

Date-fns est une excellente petite bibliothèque qui met à votre disposition tout un tas de méthodes d'aide pour travailler avec les dates et les heures en JavaScript. Il est en cours de développement actif et maintenant que Moment.js a été mis en mode maintenance, cela en fait un excellent remplacement pour Moment.js.

J'espère que cet article vous a donné suffisamment de compréhension et d'inspiration pour aller le vérifier et commencer à l'utiliser dans vos propres projets.

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *