Библиотека date-fns применяется в Angular-проектах как легковесная
альтернатива встроенному DatePipe и более тяжёлым решениям
вроде Moment.js. Основная идея интеграции заключается в использовании
чистых функций для работы с датами внутри сервисов, пайпов и
бизнес-логики, сохраняя при этом предсказуемость и удобство
тестирования.
Ключевая особенность подхода — отсутствие мутаций и модульная структура: каждая функция импортируется отдельно, что позволяет эффективно контролировать размер бандла.
Подключение библиотеки выполняется стандартным образом через пакетный менеджер:
npm install date-fns
При необходимости локализации добавляются дополнительные пакеты:
npm install date-fns
Локали в date-fns поставляются вместе с основным пакетом и импортируются точечно.
Пример использования функции форматирования:
import { format } from 'date-fns';
const result = format(new Date(), 'yyyy-MM-dd');
В Angular архитектуре предпочтительно выносить работу с датами в отдельный сервис, инкапсулирующий вызовы date-fns. Это упрощает поддержку и повышает тестируемость.
import { Injectable } from '@angular/core';
import { format, parseISO, differenceInDays } from 'date-fns';
@Injectable({
providedIn: 'root'
})
export class DateService {
formatDate(date: string | Date): string {
const parsed = typeof date === 'string' ? parseISO(date) : date;
return format(parsed, 'dd.MM.yyyy');
}
getDaysBetween(start: Date, end: Date): number {
return differenceInDays(end, start);
}
}
Такой подход позволяет централизовать форматирование и вычисления, исключая дублирование логики по компонентам.
Пайпы позволяют интегрировать date-fns прямо в шаблоны Angular.
import { Pipe, PipeTransform } from '@angular/core';
import { format } from 'date-fns';
@Pipe({
name: 'dfnsDate'
})
export class DateFnsPipe implements PipeTransform {
transform(value: Date | string, formatStr: string = 'dd.MM.yyyy'): string {
const date = typeof value === 'string' ? new Date(value) : value;
return format(date, formatStr);
}
}
Использование в шаблоне:
<div>
{{ createdAt | dfnsDate:'yyyy-MM-dd HH:mm' }}
</div>
Подобный пайп делает шаблоны компактнее, но при этом сохраняет гибкость форматирования.
date-fns поддерживает локализацию через явный импорт языковых пакетов. Это особенно важно в Angular-приложениях с мультиязычностью.
import { format } from 'date-fns';
import { ru } from 'date-fns/locale';
format(new Date(), 'PPP', { locale: ru });
Интеграция с Angular i18n обычно строится через сервис, который выбирает локаль на основе текущего языка приложения.
import { enUS, ru } from 'date-fns/locale';
const localeMap = {
en: enUS,
ru: ru
};
date-fns функции являются чистыми и не зависят от состояния, что
делает их безопасными для использования в компонентах с
OnPush стратегией.
Однако вызовы форматирования в шаблонах могут приводить к лишним пересчётам при каждом цикле обнаружения изменений.
Рекомендуемая практика — перенос вычислений в:
pure: true@Pipe({
name: 'dfnsDate',
pure: true
})
Одно из ключевых преимуществ date-fns в Angular — поддержка tree-shaking. Импортируются только используемые функции:
import { format } from 'date-fns';
В отличие от монолитных библиотек, не подключается весь функционал дат, что снижает размер production bundle.
При правильной организации импортов можно существенно уменьшить итоговый вес приложения, особенно в больших проектах.
В серверном рендеринге Angular важно учитывать отсутствие глобальных
браузерных API. date-fns не использует window или
document, поэтому совместимость с SSR обеспечивается по
умолчанию.
Особенности:
format(new Date(), 'yyyy-MM-dd HH:mm', { locale: ru });
При необходимости синхронизации времени между сервером и клиентом используется передача ISO-строк.
В реактивных формах даты часто представлены как строки или
Date-объекты. date-fns используется для нормализации и
преобразования.
import { parseISO, isValid } from 'date-fns';
const date = parseISO(control.value);
if (isValid(date)) {
// логика обработки
}
Также удобно выполнять валидацию диапазонов:
import { isAfter, isBefore } from 'date-fns';
const valid = isAfter(endDate, startDate);
Angular предоставляет встроенный DatePipe, однако
подходы различаются.
DatePipe:
date-fns:
Пример различия:
<!-- Angular -->
{{ dateValue | date:'dd.MM.yyyy' }}
// date-fns
format(dateValue, 'dd.MM.yyyy');
date-fns предпочтителен в бизнес-логике и сервисах, тогда как DatePipe удобен для простого отображения в шаблонах.
date-fns хорошо подходит для построения цепочек преобразований:
import { addDays, format, subMonths } from 'date-fns';
const result = format(
addDays(subMonths(new Date(), 1), 10),
'yyyy-MM-dd'
);
Такой стиль делает логику дат декларативной и легко тестируемой.
Чистые функции date-fns упрощают модульное тестирование. Нет необходимости мокать глобальные зависимости.
import { differenceInDays } from 'date-fns';
test('difference in days', () => {
expect(differenceInDays(
new Date('2024-01-10'),
new Date('2024-01-01')
)).toBe(9);
});
Частые проблемы при использовании date-fns в Angular:
Рациональная архитектура предполагает единый слой работы с датами, отделённый от UI-компонентов.