Jss-date — это альтернатива библиотеке дат Momentjs.

Введение

Jss-date — это мультикалендарная, легкая и богатая библиотека JavaScript для синтаксического анализа, проверки, манипулирования, форматирования и отображения дат и времени для всех сред выполнения Javascript (NodeJS, браузер и т. д.). Он поддерживает множество календарей, включая григорианский, григорианский2, персидский и исламский (хджри), в которых вы можете легко конвертировать дату и время между календарями и часовыми поясами. В частности, Jss-date поддерживает диапазон дат от 1/1/1/ до 31/12/9999 (в григорианском2, персидском и хиджрском календарях).

Фон

Казалось бы, зачем нам еще одна библиотека для работы с датами и временем, когда есть всем известная библиотека Moment?! Быстрый ответ заключается в том, что Moment.js устарел, см. Статус проекта Momentjs.

Это была популярная библиотека в течение десятилетия. Однако у Moment.js слишком много недостатков по сравнению с современными библиотеками даты и времени. Его API не является неизменяемым, он большой и не поддерживает встряхивание дерева. Даже команда Момента не рекомендует использовать их библиотеку в новых проектах.

“Теперь мы обычно считаем Moment устаревшим проектом, находящимся в режиме обслуживания. Это не мертво, но это действительно сделано . Команда _The Moment.

Несколько недостатков Moment.js

Размер посылки

Хотя Moment.js содержит множество замечательных функций и утилит, если вы работаете с веб-приложением, чувствительным к производительности, это может привести к значительным потерям производительности из-за его сложных API и большого размера пакета: 235 КБ (66 КБ в сжатом виде) по сравнению с 235 КБ (66 КБ в сжатом виде). 15 КБ (5 КБ в сжатом виде) для JSS-даты.

Сотрясение дерева

Moment.js не поддерживает встряхивание деревьев. Встряхивание дерева — это термин, обычно используемый в контексте JavaScript для описания удаления мертвого кода. В современных приложениях JavaScript мы используем сборщики модулей (например, webpack или Rollup) для автоматического удаления мертвого кода при объединении нескольких файлов JavaScript в один файл. Это способствует огромному размеру пакета Moment.js и потенциальным проблемам с производительностью.

В Jss-date все календари, локали, зоны и плагины древовидные.

неизменность

Moment.js является изменяемым и вызывает ошибки, связанные со случайным или непреднамеренным изменением переменных объекта.

Так почему же изменчивые объекты Datetime представляют собой проблему? Давайте рассмотрим пример, иллюстрирующий опасность:

var d1 = moment();
var d2 = d1.add(1, 'hour');
d1.valueOf() === d2.valueOf(); //=> true

Это происходит потому, что d1 и d2 на самом деле являются одним и тем же объектом; add() изменил объект на час позже. Обратите внимание на эквивалентный код в Jss-date:

var d1 = new DateTime();
var d2 = d1.add({ hour: 1});
d1.valueOf() === d2.valueOf(); //=> false

В этом случае метод add() возвращает новый экземпляр, оставляя d1 без изменений. Неизменяемость объекта означает, что Jss-date не требует конструкторов копирования или методов клонирования.

Как перейти с Moment.js

  1. Создайте оболочку даты и времени, которая скрывает, какую библиотеку вы используете. Если вы решите заменить библиотеку в будущем, вам нужно будет обновить только один файл.
  2. Создайте обширные модульные тесты для оболочки.
  3. Используйте eslint-plugin-you-dont-need-momentjs, чтобы найти все экземпляры Moment в вашей кодовой базе и заменить их новой оболочкой.
  4. Удалить момент.js

Как установить Jss-date и начать работу

Jss-date устанавливается через npm =› https://www.npmjs.com/package/@js-sugar/date:

npm install @js-sugar/date

Добавьте следующий код в начальную точку вашего приложения:

import { DateTime, Calendars } from '@js-sugar/date';
import { GregorianCalendar }  from '@js-sugar/date/calendars/gregorian';
import { GregorianCalendar2 } from '@js-sugar/date/calendars/gregorian2';
import { PersianCalendar }  from '@js-sugar/date/calendars/persian';
import { HijriCalendar } from '@js-sugar/date/calendars/hijri';
// You can add multiple instances of a calendar with unique id to the Calendars collection.
// Add only the calenders you want to use in your project.
Calendars.add(new GregorianCalendar('gregorian'));  
Calendars.add(new GregorianCalendar2('gregorian2'));
Calendars.add(new PersianCalendar('persian'));
Calendars.add(new HijriCalendar('hijri', -1));
// hint: GregorianCalendar is a wrapper for javascript Date object 
// but GregorianCalendar2 is independent of javascript date and it supports date range between 1/1/1 to 12/31/9999

Установить календарь по умолчанию

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

const gregorianNow = new DateTime(); // now
console.log(gregorianNow.year, gregorianNow.month, gregorianNow.day); //-> 2021, 11, 2
const gregorianDate = new DateTime(2021, 10, 26); 
console.log(gregorianDate.year, gregorianDate.month, gregorianDate.day); //-> 2021, 10, 26
// Set Persian calendar as default calendar
Calendars.default = Calendars.find('persian');
const persianNow = new DateTime(); //now
console.log(persianNow.year, persianNow.month, persianNow.day); //-> 1400, 8, 11
const persianDate = new DateTime(1400, 8, 4); 
console.log(persianDate.year, persianDate.month, persianDate.day); //-> 1400, 8, 4
// Set Hijri calendar as default calendar
Calendars.default = Calendars.find('hijri');
const hijriNow = new DateTime(); //now
console.log(hijriNow.year, hijriNow.month, hijriNow.day); //-> 1443, 3, 26
const hijriDate = new DateTime(1443,3,19); 
console.log(hijriDate.year, hijriDate.month, hijriDate.day); //-> 1443, 3, 19

Примеры кода Jss-даты

Создайте объект DateTime, предоставив календарь

const gregorianDate = new DateTime({calendar: 'gregorian'}); // now
console.log(gregorianDate.year, gregorianDate.month, gregorianDate.day) //-> 2021, 10, 26
const persianDate = new DateTime({calendar: 'persian'})  //now
console.log(persianDate.year, persianDate.month, persianDate.day) //-> 1400, 8, 4
    
const hijriDate = new DateTime({calendar: 'hijri'}) //now
console.log(hijriDate.year, hijriDate.month, hijriDate.day) //-> 1443, 3, 19 
    
const gregorian2Date = new DateTime({calendar: 'gregorian2'}) //now
console.log(gregorian2Date.year, gregorian2Date.month, gregorian2Date.day) //-> 2021, 10, 26 
// output:
2021 10 26
1400 8 4
1443 3 19
2021 10 26

Добавить и вычесть

const dt = new DateTime( { calendar: 'gregorian' }, 2020,1,1);
const dt2 = dt.add({ day: 1 });
console.log(dt2.year, dt2.month, dt2.day); //-> 2020, 1, 2
const dt = new DateTime({ calendar: 'persian'}, 1400,1,1 );
const dt2 = dt.subtract({ day: 1 });
console.log(dt2.year, dt2.month, dt2.day); //-> 1399, 12, 30

Разобрать строку

Если вы знаете формат входной строки, вы можете использовать его для ее анализа.

// Import parse plugin
import { parse } from '@js-sugar/date/plugins/parse';
const dt = parse('2012/2/6', 'Y/M/d');
console.log(dt.year, dt.month, dt.day) //-> 2012, 2, 6
const dt1 = parse("12-25-1995", "MM-dd-YYYY");
console.log(dt1.year, dt1.month, dt1.day) //-> 2012, 2, 6
const dt2 = parse('99/2/6', 'YY/M/d');
console.log(dt2.year, dt2.month, dt2.day) //-> 99, 2, 6

Точки интереса

Вы можете легко конвертировать дату и время между календарями и часовыми поясами.

Преобразование даты и времени

const gregorianDate = new DateTime({calendar: 'gregorian'}, 2021, 10, 26);
console.log(gregorianDate.year, gregorianDate.month, gregorianDate.day) //-> 2021, 10, 26
// convert gregorian to persian date
const persianDate = gregorianDate.to('persian');
console.log(persianDate.year, persianDate.month, persianDate.day) //-> 1400, 8, 4
    
// convert persian to hijri date
const hijriDate = persianDate.to('hijri');
console.log(hijriDate.year, hijriDate.month, hijriDate.day) //-> 1443, 3, 19 
// convert hijri to gregorian2 date
const gregorian2Date = hijriDate.to('gregorian2')
console.log(gregorian2Date.year, gregorian2Date.month, gregorian2Date.day) //-> 2021, 10, 26 

// output:
2021 10 26
1400 8 4
1443 3 19
2021 10 26

Изменить часовой пояс

const UTC = new DateTime({ zone: Zones.utc});
console.log("UTC-Time -> hh:" + UTC.hour + " mm:" + UTC.minute + " ss:"+ UTC.second);
let Tehran = UTC.toZone('Asia/Tehran');
console.log("Tehran-Time -> hh:" + Tehran.hour + " mm:" + Tehran.minute + " ss:"+ Tehran.second);
const Toronto = Tehran.toZone('America/Toronto');
console.log("Toronto-Time -> hh:" + Toronto.hour + " mm:" + Toronto.minute + " ss:"+ Toronto.second);
let London = Toronto.toZone('Europe/London');
console.log("London-Time -> hh:" + London.hour + " mm:" + London.minute + " ss:"+ London.second);
// output:
UTC-Time -> hh:19 mm:44 ss:28
Tehran-Time -> hh:23 mm:14 ss:28
Toronto-Time -> hh:14 mm:44 ss:28
London-Time -> hh:19 mm:44 ss:28

Изменить регион

// in this example default calendar is gregorian
const roLocale = new DateTime().toLocale('ro');
console.log(roLocale.locale.getMonthNames(roLocale.calendar)[0]);
const deLocale = roLocale.toLocale('de');
console.log(deLocale.locale.getMonthNames(deLocale.calendar)[0]);
      
const faLocale = deLocale.toLocale('fa-IR');
console.log(faLocale.locale.getMonthNames(faLocale.calendar)[0]);
// convert faLocale (from Gregorian) to Persian datetime object
const faIR = faLocale.to('persian');
console.log(faIR.locale.getMonthNames(faIR.calendar)[0]);

// output:
ianuarie
Januar
ژانویه
فروردین

URL-адреса

NPM: https://www.npmjs.com/package/@js-sugar/date
Документ API: https://js-sugar.github.io/date
Отслеживание проблем : https://github.com/js-sugar/date