Работа с датами и временем в TypeScript: от основ до продвинутых техник
Работа с датами и временем — одна из самых частых задач в веб-разработке. TypeScript, будучи надстройкой над JavaScript, наследует встроенный объект Date, но добавляет к нему строгую типизацию. В этой статье мы разберем, как эффективно работать с датами в TypeScript: от создания и форматирования до сложных манипуляций с таймзонами. Вы узнаете, как избежать типичных ошибок и сделать код более надежным и читаемым.
Основы: создание и базовые операции с датами
Объект Date в TypeScript — это тот же JavaScript-объект, но с улучшенной поддержкой типов. Рассмотрим основные способы создания дат:
// Текущая дата и время
const now: Date = new Date();
// Из строки (ISO 8601)
const specificDate: Date = new Date('2024-12-25T10:30:00Z');
// Из компонентов (год, месяц (0-11), день, часы, минуты, секунды)
const customDate: Date = new Date(2024, 11, 25, 10, 30, 0); // 25 декабря 2024
// Из миллисекунд (Unix timestamp)
const fromTimestamp: Date = new Date(1703493000000);
Важно помнить, что месяцы в JavaScript/TypeScript нумеруются с 0 (январь — 0, декабрь — 11). Это частая причина ошибок у новичков. Чтобы избежать путаницы, рекомендуется использовать строковые форматы или библиотеки.
Базовые методы для получения компонентов даты:
getFullYear()— возвращает год (4 цифры)getMonth()— месяц (0-11)getDate()— день месяца (1-31)getDay()— день недели (0 — воскресенье, 6 — суббота)getHours(),getMinutes(),getSeconds()— времяgetTime()— количество миллисекунд с 1 января 1970 года
Пример использования с типизацией:
function formatDate(date: Date): string {
const year: number = date.getFullYear();
const month: string = String(date.getMonth() + 1).padStart(2, '0');
const day: string = String(date.getDate()).padStart(2, '0');
return `${year}-${month}-${day}`;
}
const today: Date = new Date();
console.log(formatDate(today)); // "2024-12-25"
Форматирование и отображение дат
Встроенные методы форматирования дат в TypeScript ограничены. Для простых задач можно использовать toLocaleDateString() и toLocaleTimeString():
const date: Date = new Date('2024-12-25T10:30:00');
// Локализованный формат
console.log(date.toLocaleDateString('ru-RU')); // "25.12.2024"
console.log(date.toLocaleTimeString('ru-RU')); // "10:30:00"
// Полный формат
console.log(date.toLocaleString('ru-RU', {
year: 'numeric',
month: 'long',
day: 'numeric',
weekday: 'long'
})); // "среда, 25 декабря 2024 г."
Однако для сложного форматирования или строгого контроля над выводом лучше использовать специализированные библиотеки. Самой популярной является date-fns — легковесная, модульная и полностью совместимая с TypeScript.
Установка:
npm install date-fns
Пример использования:
import { format, addDays, parseISO } from 'date-fns';
import { ru } from 'date-fns/locale';
const date: Date = parseISO('2024-12-25T10:30:00');
// Форматирование
console.log(format(date, 'dd.MM.yyyy')); // "25.12.2024"
console.log(format(date, 'PPP', { locale: ru })); // "25 декабря 2024 г."
// Сложение дней
const futureDate: Date = addDays(date, 10);
console.log(format(futureDate, 'dd.MM.yyyy')); // "04.01.2025"
Другие полезные функции из date-fns: differenceInDays, isBefore, isAfter, startOfMonth, endOfWeek и многие другие. Библиотека позволяет писать чистый, функциональный код без мутации исходных объектов.
Сравнение и манипуляции с датами
Сравнение дат в TypeScript может быть неочевидным из-за особенностей объекта Date. Операторы > и < работают корректно, но для строгого равенства нужно использовать getTime():
const date1: Date = new Date('2024-12-25');
const date2: Date = new Date('2024-12-25');
// Неправильно (сравниваются ссылки)
console.log(date1 === date2); // false
// Правильно (сравниваются миллисекунды)
console.log(date1.getTime() === date2.getTime()); // true
// Использование date-fns
import { isEqual, isBefore, isAfter } from 'date-fns';
console.log(isEqual(date1, date2)); // true
Для манипуляций с датами (добавление дней, месяцев, лет) также рекомендуется использовать библиотеки, так как ручные вычисления могут привести к ошибкам, особенно при работе с високосными годами и переходом на летнее время.
import { addMonths, subDays, startOfYear, endOfMonth } from 'date-fns';
const today: Date = new Date();
const nextMonth: Date = addMonths(today, 1);
const lastWeek: Date = subDays(today, 7);
const yearStart: Date = startOfYear(today);
const monthEnd: Date = endOfMonth(today);
Работа с часовыми поясами (таймзонами)
Одна из самых сложных тем — работа с часовыми поясами. Встроенный объект Date всегда работает в локальном времени пользователя или в UTC. Для работы с произвольными таймзонами необходима дополнительная библиотека.
Лучшее решение для TypeScript — date-fns-tz (расширение для date-fns) или Luxon. Рассмотрим пример с date-fns-tz:
npm install date-fns-tz
import { format, utcToZonedTime, z