Работа с объектами Date

Объект Date — один из трёх форматов, которые принимает функция format. Он является нативным для JavaScript и наиболее удобен в проектах с TypeScript или строгой типизацией, поскольку тип Date однозначно определён и не допускает двусмысленности.


Базовый пример

import { format } from 'timeago.js';

const date = new Date('2025-05-26T08:00:00Z');

format(date, 'ru');
// → "4 часа назад"

Создание объекта Date из разных источников

Из строки ISO 8601:

const date = new Date('2025-05-26T10:30:00.000Z');
format(date, 'ru');

Из числа (timestamp):

const date = new Date(1716720000000);
format(date, 'ru');

Из компонентов:

// Год, месяц (0-11), день, часы, минуты, секунды
const date = new Date(2025, 4, 26, 10, 30, 0);
format(date, 'ru');

Текущий момент:

const now = new Date();
format(now, 'ru');
// → "только что"

Арифметика с объектом Date

Часто требуется вычислить дату, отстоящую на определённый промежуток:

const date = new Date();
date.setHours(date.getHours() - 3);

format(date, 'ru');
// → "3 часа назад"

Аналогично для будущего:

const future = new Date();
future.setDate(future.getDate() + 7);

format(future, 'ru');
// → "через 1 неделю"

Объект Date и часовые пояса

Объект Date хранит время в UTC, но методы getHours(), getDay() и т.д. возвращают значения в локальном часовом поясе устройства.

Функция format вычисляет разницу между .getTime() (UTC-timestamp) входной даты и Date.now() (также UTC). Поэтому часовой пояс не влияет на вычисление разницы:

// Эти два вызова дадут одинаковый результат,
// несмотря на разные строковые представления
format(new Date('2025-05-26T10:00:00Z'));
format(new Date('2025-05-26T13:00:00+03:00'));

Разница между локальным и UTC временем

const local = new Date(2025, 4, 26, 10, 0, 0); // локальное время
const utc   = new Date('2025-05-26T10:00:00Z'); // UTC

// Если UTC-смещение не ноль, getTime() вернёт разные значения
console.log(local.getTime() !== utc.getTime()); // вероятно true

При получении дат из API всегда уточняйте, в каком часовом поясе они переданы.


Сравнение Date.now() и new Date()

const ts1 = Date.now();       // число (мс)
const ts2 = new Date();       // объект Date

// Оба эквивалентны для timeago.js
format(ts1);
format(ts2);

Оба варианта корректны. Date.now() предпочтительнее, когда дата нужна только для вычисления разницы — он не создаёт объект.


Объект Date в TypeScript

В TypeScript тип Date обеспечивает статическую проверку:

import { format } from 'timeago.js';

function formatDate(date: Date): string {
  return format(date, 'ru');
}

const created = new Date(apiResponse.createdAt);
const label = formatDate(created);

TypeScript не допустит передачи string туда, где ожидается Date, — это предотвращает распространённые ошибки.


Работа с массивом объектов Date

const dates = [
  new Date('2025-05-26T10:00:00Z'),
  new Date('2025-05-25T08:00:00Z'),
  new Date('2025-05-20T15:00:00Z'),
];

dates.map(d => format(d, 'ru'));
// → ["4 часа назад", "1 день назад", "6 дней назад"]

Объект Date и render()

Функция render() работает с DOM-элементами через атрибут datetime. Перед записью объект Date нужно конвертировать в строку:

const date = new Date('2025-05-26T10:00:00Z');

const el = document.getElementById('time');
el.setAttribute('datetime', date.toISOString());

render(el, 'ru');

Метод toISOString() всегда возвращает строку в UTC с суффиксом Z, что гарантирует однозначность.


Invalid Date

Передача невалидного объекта Date приводит к непредсказуемому результату:

const invalid = new Date('not-a-date');
console.log(invalid.getTime()); // NaN

format(invalid); // NaN years ago или ошибка

Защита от Invalid Date:

function isValidDate(date) {
  return date instanceof Date && !isNaN(date.getTime());
}

function safeFormat(date, locale = 'ru') {
  if (!isValidDate(date)) return '';
  return format(date, locale);
}

Объект Date из разных библиотек

timeago.js принимает любой объект с интерфейсом, совместимым с Date. Это работает с Moment.js, Day.js, Luxon при явной конвертации:

// Moment.js
import moment from 'moment';
const m = moment('2025-05-26');
format(m.toDate(), 'ru');

// Day.js
import dayjs from 'dayjs';
const d = dayjs('2025-05-26');
format(d.toDate(), 'ru');

// Luxon
import { DateTime } from 'luxon';
const l = DateTime.fromISO('2025-05-26');
format(l.toJSDate(), 'ru');

Производительность

Создание объекта Date — дешёвая операция. Для единичных вызовов нет причин оптимизировать. При обработке тысяч записей в цикле лучше использовать timestamp напрямую:

// Чуть эффективнее для больших объёмов
posts.map(p => format(p.timestamp, 'ru'));