15 сентября 2020 года команда сопровождающих Moment.js заявила, что работа одной из самых популярных в мире библиотек данных JavaScript подошла к концу.

Он не нуждается в представлении: по данным NPM, по состоянию на сентябрь 2020 года его загружали более 14 миллионов в неделю и более 46 000 зависимых пакетов с открытым исходным кодом. Moment.js существует с 2011 года, но у его разработчиков есть свои причины прекратить его активную поддержку, которая также включает неизменность и поддержку дрожания дерева.

Не нужно скулить по этому поводу, но есть веская причина взглянуть на его преемников. Очевидно, я должен вам сказать, что вам не нужно сразу перебирать все свои проекты и заменять Moment.js; если у вас не так много мест, где вы его используете, продолжайте и обновляйте его, но с этого момента все, над чем вы начинаете работать, вероятно, больше не должно его использовать.

Вот обзорное сравнение нескольких библиотек дат, которые рекомендуются в качестве возможной замены. Мы будем придерживаться TypeScript как все более популярного языка, используемого во многих проектах (я имею в виду, что их действительно много).

Для начала давайте создадим довольно простое приложение React, чтобы мы могли быстро начать это путешествие и сразу же увидеть результаты:
yarn create react-app play-date — template typescript

Момент.js

Давайте взглянем на Moment.js и посмотрим, насколько просто начать его использовать (или мне теперь сказать было?).

Первое, что нам нужно, прежде чем использовать Moment.js в любом проекте, это установить его:
npm i moment или yarn add moment

Затем импортируйте его в компонент, и все готово:
import moment from 'moment';

Дата как объект
const test1 = new Date('2018–01–16'); // Date

Во-первых, нам нужно преобразовать его:
const obj1 = moment(test1); // Moment
Вот и все — красиво и просто! Moment.js берет объект Date «как есть» и превращает его в собственный объект, чтобы мы могли с ним работать.

А если нам нужно знать, какой год внутри, то мы легко можем его получить:
obj1.year(); // number

Или посчитайте, сколько дней прошло с тех пор:
moment().diff(obj1, 'days'); // number

Дата в виде строки
const test2 = '2016–07–20'; // string

Преобразуйте его:
moment(test2); // Moment
Moment.js также принимает строку «как есть», поэтому вам следует заботиться только о ее формате.
Хотя Moment не ограничивает вас каким-то особым форматом, он может не распознать какое-то настоящее барахло.

Day.js

Затем переходим к ближайшему преемнику Момента — Day.js. Если вы когда-либо использовали Moment.js, заменить его на Day.js должно быть очень легко, это не совсем то же самое, но все же стоит попробовать.

Начните использовать Day.js, добавив его в свой проект:
npm i dayjs или yarn add dayjs

Затем импортируйте его:
import dayjs from 'dayjs';

Даже тем из вас, кто никогда не слышал о «Моменте» до двух предыдущих строк, должно показаться, что вы видели это раньше. И вы были бы правы, если бы сказали, что это выглядит точно так же, как установка и импорт Момента.

Дата как объект
const test1 = new Date('2018–01–16'); // Date

Day.js, возможно, не является заменой Moment.js, но он дает вам довольно похожий API и использует ту же концепцию превращения всего в отдельный объект.

Преобразование:
const obj1 = dayjs(test1); // Dayjs

А если нам надо узнать, какой год внутри, то мы его просто получаем:
obj1.year(); // number

Или просто посчитайте, сколько дней прошло с тех пор:
dayjs().diff(obj1, 'day'); // number

Особенность использования Moment.js заключается в том, что вы можете подсчитывать дни или годы, а также день или год — это вообще не имеет значения. Чего нельзя сказать о Day.js, но, с другой стороны, это цена, которую вы платите за действительно легкую библиотеку.

Дата в виде строки
const test2 = '2016–07–20'; // string

И снова нам нужно преобразовать его. Day.js, как и Moment.js, будет анализировать любую строку с учетом ее ISO 8601. Но если вы хотите проанализировать что-то отличное от этого, вы должны предоставить ей желаемый формат:
dayjs(test2, 'YYYY-MM-DD'); // Dayjs

Люксон

Наш следующий участник дает нам тонкий намек на то, что его основные сопровождающие почти такие же, как у Moment.

Сделайте обычный шаг и добавьте Luxon в свой проект:
npm i luxon или yarn add luxon

Немного отступите. Помните, мы решили продолжить работу с TypeScript? Ну, Luxon, в отличие от других библиотек, не поставляется с собственными определениями типов, поэтому ваша современная IDE должна кричать, когда вы пытаетесь импортировать ее. Вот как можно добавить поддержку TypeScript:
npm i @types/luxon или yarn add @types/luxon

Затем вы можете перейти к другому обычному шагу:
import { DateTime } from 'luxon';

Дата как объект
const test1 = new Date('2018–01–16'); // Date

Если вы считаете, что нам нужно обернуть (или преобразовать) дату, чтобы использовать ее, то вы правы:
const obj1 = DateTime.fromJSDate(test1); // DateTime
В отличие от Moment.js, Luxon не предоставит вам единую «точку входа» для выполнения Это. Обратитесь к его руководству или используйте завершение кода, чтобы проанализировать дату.

Вернуть значение года:
obj1.toFormat('yyyy'); // string

Здесь мы получаем результат в виде строки, потому чтоtoFormat()может дать нам почти что угодно с параметром token.

Подсчитайте, сколько дней прошло с тех пор:
DateTime.fromJSDate(new Date()).diff(obj1, 'days').as('days'); // number
Синтаксис очень старается быть похожим на Moment.js, но он намного длиннее, чем лично мне нравится, и дает ужасно точный результат.

Дата в виде строки
const test2 = '2016–07–20'; // string

И снова нам нужно преобразовать его, используя соответствующий метод. Хотя мы могли бы использовать fromFormat(), если бы эта строка была не в формате ISO 8601, но давайте пока остановимся на fromISO():
DateTime.fromISO(test2); // DateTime

дата-fns

Чтобы перейти к следующей библиотеке, нам нужно добавить date-fns как обычно:
npm i date-fns или yarn add date-fns

И здесь возникает его первая ловушка — вы не можете импортировать его, как Moment.js или Luxon, каждую из функций date-fns нужно добавлять в оператор импорта отдельно, поэтому вы не можете использовать преимущества автозавершения кода.
Это требует, чтобы вы знали, какая функция вам нужна, или обратитесь к руководству, чтобы найти нужную:
import { differenceInDays, getYear } from 'date-fns';

Дата как объект
const test1 = new Date('2018–01–16'); // Date

Эта библиотека основана на так называемых «вспомогательных функциях», которые полагаются на собственные манипуляции с объектами Date, что действительно здорово. Поэтому нам не нужно преобразование, чтобы использовать его сразу!

Давайте снова получим год:
getYear(test1); // number

И посчитайте, сколько дней прошло с тех пор:
differenceInDays(new Date(), test1); // number

Дата в виде строки
const test2 = '2016–07–20'; // string

К сожалению, date-fns не смог распознать для нас формат строки, поэтому для его анализа мы должны явно указать формат строки, что не имеет значения, если ваш проект хорошо документирован и непротиворечив:
parse(test2, 'yyyy-MM-dd', new Date()); // Date

Все примеры кода здесь доступны на GitHub в приложении React.

Должен сказать, что этот краткий обзор возможных замен Moment не претендует на роль полного руководства по этим библиотекам или полного списка «Что мне использовать вместо Moment.js?».
Если вы знаете лучшие инструменты — пожалуйста, сообщите всем, упомянув их в комментариях.

Первоначально опубликовано на dev.to.