Работа с датами и временем в контексте баз данных требует строгой дисциплины в выборе форматов, единиц хранения и стратегии сериализации. Luxon предоставляет слой абстракции над стандартным объектом Date, устраняя множество проблем, связанных с часовыми поясами, локалями и неоднозначностью временных меток.
В Luxon центральной сущностью является DateTime. Этот
объект не предназначен для прямого хранения в базе данных. Его задача —
представление момента времени с учётом временной зоны, локали и
формата.
Перед записью в базу данных DateTime всегда приводится к
одному из канонических форматов:
Ключевой принцип: база данных не должна хранить «объект времени», она хранит только его представление.
Наиболее безопасный формат для обмена между приложением и базой данных — ISO 8601.
Luxon предоставляет метод:
dateTime.toISO()
Пример результата:
2026-05-23T14:35:12.123Z
Особенность:
Unix timestamp удобен для индексации и сравнений.
В Luxon:
dateTime.toMillis()
или
dateTime.toSeconds()
Пример:
const dt = DateTime.now().toUTC();
const ts = dt.toMillis();
Преимущества:
Недостатки:
Многие СУБД поддерживают собственный тип:
TIMESTAMP / TIMESTAMPTZDATETIME / TIMESTAMPLuxon не взаимодействует с SQL напрямую, но обеспечивает корректную подготовку значения:
dateTime.toUTC().toISO()
или
dateTime.toJSDate()
Перед сохранением данных важно привести DateTime к
стабильному виду.
Основная ошибка при работе с датами — сохранение локального времени без нормализации.
import { DateTime } fr om "luxon";
const dt = DateTime.local().setZone("Europe/Berlin");
const normalized = dt.toUTC();
Результат:
const event = {
title: "Meeting",
start_time: DateTime.now().toUTC().toISO()
};
SQL:
INS ERT INTO events (title, start_time)
VALUES ($1, $2);
const event = {
created_at: DateTime.now().toMillis()
};
Используется при схемах:
created_at BIGINT NOT NULL
Данные из базы всегда приходят в одном из трёх видов:
import { DateTime } from "luxon";
const dt = DateTime.fromISO(row.start_time);
const dt = DateTime.fromMillis(row.created_at);
const dt = DateTime.fromSQL(row.start_time);
SQL формат зависит от базы:
2026-05-23 14:35:12
Базы данных не должны интерпретировать временные зоны на уровне бизнес-логики. Luxon выполняет эту задачу до записи.
Стандартный подход:
const utcTime = DateTime.now().toUTC();
Сохранение:
utcTime.toISO();
Восстановление:
const dt = DateTime.fromISO(dbValue, { zone: "utc" });
DateTime.local().toISO(); // нежелательно для БД
Проблемы:
Prisma возвращает Date, поэтому требуется
конвертация:
const dt = DateTime.fromJSDate(record.createdAt);
Перед записью:
data.createdAt = DateTime.now().toUTC().toJSDate();
Sequelize может автоматически конвертировать Date, но
Luxon используется для логики:
const dt = DateTime.fromJSDate(user.createdAt);
При использовании Knex контроль форматов полностью на стороне приложения:
await knex("events").insert({
start_time: DateTime.now().toUTC().toISO()
});
Часто возникает двойная сериализация: БД → API → клиент.
Из БД:
const dt = DateTime.fromISO(row.start_time);
В API:
return {
start_time: dt.toISO()
};
return {
start_time: dt.toMillis()
};
Выбор зависит от архитектуры:
Подходит для:
Характеристики:
Подходит для:
Характеристики:
Подходит для:
DateTime.local().toISO(); // риск
DateTime.now().toUTC().toISO(); // корректно
DateTime.fromISO(dbValue).toLocal();
Приводит к смещению времени.
DateTime.fromJSDate(date); // зона неявна
Правильнее:
DateTime.fromJSDate(date, { zone: "utc" });
// нельзя
ins ert({ time: DateTime.now() });
База данных не понимает объект Luxon.
При проектировании схемы хранения времени важно учитывать:
Пример диапазонного запроса:
SEL ECT *
FR OM events
WH ERE start_time BETWEEN '2026-05-01' AND '2026-06-01';
При epoch:
WHERE start_time BETWEEN 1714521600000 AND 1717200000000;
function serializeDateTime(dt) {
return dt.toUTC().toISO();
}
function deserializeDateTime(val ue) {
return DateTime.fromISO(val ue, { zone: "utc" });
}
const event = {
start: serializeDateTime(DateTime.now()),
};
Luxon выступает как промежуточный слой между:
Ключевой принцип архитектуры: база данных хранит данные, Luxon управляет смыслом времени.