Продвинутая работа с датами и временем в TypeScript

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Продвинутая работа с датами и временем в TypeScript

Работа с датами и временем — одна из самых частых и одновременно сложных задач в веб-разработке. В TypeScript, благодаря строгой типизации, мы можем избежать многих ошибок, связанных с манипуляциями датами, но стандартный объект Date имеет ряд ограничений. В этой статье мы рассмотрим продвинутые подходы к работе с датами и временем, включая использование современных библиотек, типизацию, работу с часовыми поясами и парсинг сложных форматов.

1. Проблемы нативного Date и их решение с помощью TypeScript

Стандартный Date в JavaScript крайне неудобен для сложных операций:

  • Мутабельность: методы вроде setDate() изменяют исходный объект.
  • Отсутствие форматирования: нет встроенного способа вывести дату в формате "DD.MM.YYYY".
  • Слабая работа с часовыми поясами: Date хранит время в UTC, а методы getHours() возвращают локальное время.
  • Проблемы с парсингом: new Date("2023-01-01") может интерпретироваться по-разному в разных браузерах.

TypeScript помогает, позволяя нам создавать обертки и утилиты. Например, можно определить строгие типы для форматирования:

type DateFormat = 'DD.MM.YYYY' | 'YYYY-MM-DD' | 'HH:mm:ss';

function formatDate(date: Date, format: DateFormat): string {
  const day = String(date.getDate()).padStart(2, '0');
  const month = String(date.getMonth() + 1).padStart(2, '0');
  const year = date.getFullYear();
  const hours = String(date.getHours()).padStart(2, '0');
  const minutes = String(date.getMinutes()).padStart(2, '0');
  const seconds = String(date.getSeconds()).padStart(2, '0');

  switch (format) {
    case 'DD.MM.YYYY':
      return `${day}.${month}.${year}`;
    case 'YYYY-MM-DD':
      return `${year}-${month}-${day}`;
    case 'HH:mm:ss':
      return `${hours}:${minutes}:${seconds}`;
    default:
      return '';
  }
}

// Использование
const now = new Date();
console.log(formatDate(now, 'DD.MM.YYYY')); // "15.10.2023"

Такой подход гарантирует, что мы не передадим неверный формат в функцию, так как TypeScript проверит тип на этапе компиляции.

2. Использование библиотеки date-fns: чистота и функциональность

date-fns — это современная библиотека для работы с датами, которая идеально подходит для TypeScript. Её главные преимущества:

  • Иммутабельность: все функции возвращают новые объекты, не изменяя исходные.
  • Модульность: вы импортируете только нужные функции, что уменьшает размер бандла.
  • Типизация: библиотека имеет встроенную поддержку TypeScript.

Установка:

npm install date-fns

Примеры продвинутого использования:

import { format, addDays, differenceInDays, isWeekend, parseISO } from 'date-fns';

// Форматирование
const date = new Date(2023, 9, 15); // 15 октября 2023
console.log(format(date, 'dd.MM.yyyy')); // "15.10.2023"
console.log(format(date, 'EEEE, MMMM do yyyy')); // "Sunday, October 15th 2023"

// Арифметика
const nextWeek = addDays(date, 7);
console.log(format(nextWeek, 'dd.MM.yyyy')); // "22.10.2023"

// Разница между датами
const startDate = new Date(2023, 0, 1);
const endDate = new Date(2023, 11, 31);
const diff = differenceInDays(endDate, startDate);
console.log(diff); // 364

// Проверка выходного дня
console.log(isWeekend(date)); // true (воскресенье)

// Парсинг ISO строки
const parsed = parseISO("2023-10-15T10:30:00Z");
console.log(format(parsed, 'HH:mm')); // "13:30" (с учетом часового пояса)

Важно: date-fns работает с объектами Date, поэтому вы можете легко комбинировать её с нативным кодом. Для сложных проектов это лучший выбор, так как она не расширяет прототипы (в отличие от Moment.js).

3. Работа с часовыми поясами и библиотека date-fns-tz

Одна из самых сложных задач — корректная работа с разными часовыми поясами. Нативный Date не хранит информацию о часовом поясе, а только преобразует время в UTC. Библиотека date-fns-tz решает эту проблему.

Установка:

npm install date-fns-tz

Примеры:

import { format, utcToZonedTime, zonedTimeToUtc } from 'date-fns-tz';

// Конвертация UTC времени в заданный часовой пояс
const utcDate = new Date('2023-10-15T12:00:00Z'); // 12:00 UTC
const timeZone = 'Europe/Moscow'; // UTC+3

const moscowTime = utcToZonedTime(utcDate, timeZone);
console.log(format(moscowTime, 'HH:mm')); // "15:00"

// Создание даты в конкретном часовом поясе
const nyTime = 'America/New_York';
const nyDate = zonedTimeToUtc('2023-10-15 10:00:00', nyTime);
console.log(nyDate.toISOString()); // "2023-10-15T14:00:00.000Z"

Почему это важно? Представьте, что вы работаете с международным приложением. Пользователь из Нью-Йорка создает событие на 10:00 утра. Сервер должен сохранить это время в UTC, чтобы пользователь из Москвы увидел корректное локальное время. date-fns-tz делает эту логику прозрачной и типобезопасной.

Также можно определить строгие типы для часовых поясов:

type TimeZone = 'Europe/Moscow' | 'America/New_York' | 'Asia/Tokyo';

function getLocalTime(date: Date, tz: TimeZone): string {
  const zonedDate = utcToZonedTime(date, tz);                

Блоги

Рекомендаций по книгам