Статьи

Введение в date-fns — облегченная библиотека дат JavaScript

Введение в date-fns

Работа с датами в JavaScript — это боль. Методы родной даты часто бывают многословными и иногда несовместимыми, что также делает их подверженными ошибкам. Но хорошие новости под рукой. Существует несколько библиотек, которые помогают избавиться от устаревших манипуляций. Эти библиотеки относятся к датам JavaScript, а jQuery — к нативному DOM API.

Позвольте привести пример. Это принятый ответ на вопрос переполнения стека, спрашивающий, как получить последний день месяца :

var t = new Date(); alert( new Date(t.getFullYear(), t.getMonth() + 1, 0, 23, 59, 59) ); 
Смотреть Изучить синтаксис JavaScript и принципы программирования
Включите ваш код JavaScript. Сила современного Интернета.

Конечно, это работает, но не сразу очевидно, что представляют собой числа после getMonth . Теперь сопоставьте это со значительно более читабельным:

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

Этот метод lastDayOfMonth предоставлен date-fns , самопровозглашенным всеобъемлющим набором инструментов для манипулирования датами JavaScript в браузере и Node.js.

В этой статье я собираюсь показать вам, как начать работать с date-fns. После прочтения вы сможете добавить его в свои проекты и использовать многочисленные вспомогательные методы для удобного управления датами. Это сделает код вроде t.getMonth() + 1, 0, 23, 59, 59 в прошлое.

Так почему бы просто не использовать Moment.js?

Слон в комнате — Момент.js . Эта библиотека, несомненно, стала стандартом де-факто для работы с датами в JavaScript. Так почему бы не использовать это? Зачем нам нужна еще одна библиотека дат JavaScript?

Ну, по словам Саша Косса , создателя date-fns, у Moment.js есть несколько присущих ему проблем, которые побудили его создать date-fns. Саша рассказывает об этих проблемах на странице проекта GitHub , но в двух словах:

  • Moment.js является изменяемым, что может вызвать ошибки.
  • Он имеет сложный OOP API (который удваивает проблему изменчивости).
  • Из-за сложного API это приводит к снижению производительности.
  • Его размер сборки велик при использовании с Webpack, так как файлы локали включены в комплект.

Давайте сопоставим это с date-fns (взято с домашней страницы проекта ):

  • Date-fns является неизменным, всегда возвращая новую дату, а не изменяя ту, которую вы передаете.
  • У него простой API. У вас всегда есть одна функция, которая делает одну вещь.
  • Это быстро. Вы можете быть уверены, что ваши пользователи будут иметь лучший пользовательский опыт.
  • Это идеальный компаньон для Webpack. Благодаря стилю «функция для файла» вы можете выбрать то, что вам нужно, и прекратить раздутый проект с бесполезной функциональностью.

Для меня особенность, которая заставляет это сиять, является его удобством использования. Используя его в веб-проекте, вы можете просто взять date-fns из CDN, поместить его на свою страницу и получить прибыль. Подробнее об этом дальше …

Установка

Существует множество способов установить библиотеку.

Он доступен в виде пакета npm:

 npm install date-fns --save 

Или через пряжу:

 yarn add date-fns 

Или Бауэр:

 bower install date-fns 

Или из CDN:

 <script src="https://cdnjs.cloudflare.com/ajax/libs/date-fns/1.28.5/date_fns.min.js"/> 

Если вы выбрали этот метод, обратите внимание, что библиотека находится в пространстве имен под объектом dateFns , так же, как jQuery — в пространстве имен в $ .

 <script> console.log( dateFns.isToday(new Date()) ); </script> 

Date-fns Основное использование

Предполагая, что вы используете загрузчик модулей, вам могут потребоваться только те части, которые вам нужны. В следующем примере показано, как форматировать дату .

 const format = require('date-fns/format'); console.log( format(new Date(2017, 6, 6), 'MM/DD/YYYY') ); // '06/07/2017' 

Хотите изменить язык? Нет проблем:

 const format = require('date-fns/format'); const deLocale = require('date-fns/locale/de') // German console.log( format(new Date(2017, 6, 6), 'DD MMMM YYYY', { locale: deLocale }) ); // 06 Juli 2017 

Вот список поддерживаемых языков .

Если вы работаете в браузере, не забудьте повесить любые вызовы вспомогательных методов на объекте dateFns . Вот как определить последний день месяца, используя метко названный метод lastDayOfMonth :

 <script src="https://cdnjs.cloudflare.com/ajax/libs/date-fns/1.28.5/date_fns.min.js"></script> <script> console.log( dateFns.lastDayOfMonth( new Date(2017, 6, 7) ) ); // Mon Jul 31 2017 00:00:00 GMT+0200 (CEST) </script> 

Обратите внимание, что у date-fns есть эквивалентные методы для определения последнего дня недели , квартала и года .

Неизменность, Чистота и Простота

Одним из преимуществ продажи date-fns является то, что его функции понятны и просты. Это приводит к легкому для понимания коду, который легче отлаживать, когда что-то идет не так.

Позвольте мне продемонстрировать это, используя Moment.js в качестве контрпримера. Как упоминалось ранее, даты в Moment являются изменяемыми, что может привести к неожиданному поведению.

 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()); // 2017-07-08T22:00:00.000Z // 2017-07-11T22:00:00.000Z 

Здесь есть пара вещей, на которые стоит обратить внимание. Функция add момента не суетится в том порядке, в котором она принимает свои аргументы (хотя первый метод теперь выдаст предупреждение об устаревании). Но более запутанным является то, что если вы вызываете add несколько раз подряд, вы не получите тот же результат, потому что объекты Moment изменчивы:

 mNow.add(3, 'day'); // add 3 days mNow.add(3, 'day'); // adds 3 **more** days 

Теперь сравните это с date-fns, который хранит аргументы в одном порядке и всегда возвращает один и тот же результат, возвращая новый объект Date для каждого вызова.

 let addDays = required('date-fns/add_days'); addDays(now, 3); // (April 30, 2017) addDays(now, 3); // (April 30, 2017) addDays(now, 3); // (April 30, 2017) 

Также обратите внимание на то, как имя метода является более выразительным ( addDays вместо просто add ), сохраняя согласованность и имея один метод для выполнения одной и только одной вещи.

Сравнение дат

Если вы посмотрите список сообщений на канале JavaScript SitePoint, вы увидите, что некоторые из них перечислены как опубликованные в определенный день, тогда как другие перечислены как опубликованные X дней назад. Это может занять некоторое время, если вы попытаетесь реализовать это в обычном JavaScript, но с date-fns это очень просто — просто используйте метод distanceInWords .

Давайте сравним две разные даты.

 const distanceInWords = require('date-fns/distanceInWords'); const startDate = new Date(2017, 3, 27); // (April 27, 2017) const endDate = new Date(2018, 3, 27); // (April 27, 2018) console.log( distanceInWords(startDate, endDate) ); // "about 1 year" 

В date-fns, если вы хотите узнать разницу в другой единице, вы можете заменить любое из следующего:

  • миллисекунды
  • секунд
  • минут
  • часов
  • дней
  • Месяцы
  • лет

Где имена методов имеют differenceIn[any of the above here] как differenceInDays .

Работа с коллекциями дат

Date-fns имеет несколько очень удобных вспомогательных методов, которые вы можете использовать для манипуляции коллекциями дат всевозможными способами.

Заказ коллекции дат

В следующем примере используется CompareAsc для сортировки дат по возрастанию. Для этого возвращается 1, если первая дата идет после второй, -1, если первая дата предшествует второй, или 0, если даты равны.

 const compareAsc = require('date-fns/compare_asc'); 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); // [ 2005-01-01, 2010-01-01, 2015-01-01 ] 

Как видите, даты теперь в порядке возрастания.

compareAsc методом для compareAsc является CompareDesc .

 const compareDesc = require('date-fns/compare_desc'); ... const sortedDates = arr.sort(compareDesc); // [ 2015-01-01, 2010-01-01, 2005-01-01 ] 

Генерация дней между двумя датами

Чтобы сгенерировать дни между двумя датами, вы можете использовать метод addDays, который мы встречали ранее, а также помощник eachDay, которая возвращает массив дат в указанном диапазоне.

 const addDays = require('date-fns/add_days'); const eachDay = require('date-fns/each_day'); const today = new Date(); const dayAWeekFromNow = addDays(today, 7); const thisWeek = eachDay(today, dayAWeekFromNow); console.log(thisWeek); // [ 2017-07-03, 2017-07-04, 2017-07-05, 2017-07-06, 2017-07-07, 2017-07-08, 2017-07-09, 2017-07-10 ] 

Нахождение ближайшей даты

Найти ближайшую дату к определенной дате в массиве дат можно с помощью метода closestTo . Этот фрагмент кода следует из предыдущего примера:

 const closestTo = require('date-fns/closest_to'); ... const christmas = new Date(2017, 11, 25); const closestToChristmasDate = closestTo(christmas, thisWeek); // 2017-07-10T 

Существует также метод closestIndexTo, если вы хотите вместо этого получить индекс массива.

Часовые пояса

Недостатком date-fns является то, что в настоящее время у него нет вспомогательных функций часового пояса, как у Moment.js. Этот ответ о переполнении стека на самом деле дает некоторое представление о том, как собственные объекты Date самом деле не хранят данные «реального часового пояса». Однако date-fns всегда возвращает местный часовой пояс, в котором выполняется код.

В этой теме вы заметите, что они упоминают несколько ограниченный способ установки часовых поясов в JavaScript. Как отмечается в ответе, это не всеобъемлющее решение, но оно работает для многих сценариев, которые требуют только преобразования выходных данных (из UTC или местного времени в определенный часовой пояс).

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

В действительности, часовые пояса — это сложная проблема, поэтому MomentJS имеет для этого отдельную библиотеку. Есть также планы добавить поддержку часовых поясов для date-fns , но на момент написания, это все еще в стадии разработки.

Вывод

Date-fns — отличная небольшая библиотека, которая предлагает вам целый ряд вспомогательных методов для работы с датами в JavaScript. Я надеюсь, что эта статья дала вам достаточно понимания и вдохновения, чтобы проверить и начать использовать ее в своих собственных проектах. Библиотека находится в стадии активной разработки, и версия 2 (надеюсь) не за горами.

После этого я оставлю вас в вашем путешествии, чтобы начать работу с date-fns, пожалуйста, дайте мне знать, как ваш опыт работы с date-fns в комментариях ниже.