Работа с датой и временем относится к числу наиболее сложных областей прикладного программирования. Ошибки часто возникают не из-за вычислений, а из-за смешивания различных типов временных данных:
Стандартный объект Date в JavaScript объединяет
практически всё в единую сущность, что приводит к неоднозначности и
ошибкам. Библиотека Js-joda решает эту проблему через строгую модель
типов, заимствованную из Java Time API.
Типобезопасность в Js-joda означает:
LocalDate хранит:
В объекте отсутствуют:
const { LocalDate } = require('@js-joda/core');
const date = LocalDate.of(2025, 3, 15);
console.log(date.toString());
// 2025-03-15
Попытка получить время невозможна:
date.hour();
Возникнет ошибка, поскольку LocalDate не содержит
времени.
Это фундаментальный принцип строгой типизации: объект предоставляет только те операции, которые действительно имеют смысл.
LocalTime хранит:
Дата отсутствует полностью.
const { LocalTime } = require('@js-joda/core');
const time = LocalTime.of(14, 30);
console.log(time.toString());
// 14:30
Операции с календарными днями недоступны:
time.plusDays(1);
Такого метода нет, потому что время суток не связано с календарной датой.
LocalDateTime объединяет:
Но всё ещё не содержит:
const { LocalDateTime } = require('@js-joda/core');
const dateTime = LocalDateTime.of(2025, 3, 15, 14, 30);
console.log(dateTime.toString());
// 2025-03-15T14:30
Это локальное представление времени, которое нельзя трактовать как абсолютный момент времени.
ZonedDateTime включает:
const { ZonedDateTime, ZoneId } = require('@js-joda/core');
const zoned = ZonedDateTime.now(
ZoneId.of('Europe/Moscow')
);
console.log(zoned.toString());
Теперь объект представляет конкретный момент времени в определённой временной зоне.
Одно из главных преимуществ Js-joda — предотвращение невалидных операций.
Классический JavaScript допускает опасные конструкции:
const date = new Date();
date.setHours(50);
Интерпретация зависит от внутренней логики объекта.
Js-joda избегает подобных неоднозначностей.
Преобразования выполняются только явно.
const { LocalDate, LocalTime } = require('@js-joda/core');
const date = LocalDate.of(2025, 3, 15);
const time = LocalTime.of(10, 45);
const dateTime = date.atTime(time);
console.log(dateTime.toString());
// 2025-03-15T10:45
Невозможно случайно объединить объекты автоматически.
const { ZoneId } = require('@js-joda/core');
const zoned = dateTime.atZone(
ZoneId.of('Asia/Almaty')
);
Разработчик обязан явно указать временную зону.
Все объекты Js-joda неизменяемы.
Это означает:
const { LocalDate } = require('@js-joda/core');
const original = LocalDate.of(2025, 1, 1);
const changed = original.plusDays(10);
console.log(original.toString());
// 2025-01-01
console.log(changed.toString());
// 2025-01-11
Исходный объект остаётся неизменным.
Period представляет календарный период:
const { Period } = require('@js-joda/core');
const period = Period.ofMonths(2);
Добавление периода к времени невозможно:
const time = LocalTime.of(10, 0);
time.plus(period);
Это вызовет ошибку.
Причина очевидна: время суток нельзя увеличить на календарный месяц.
Duration представляет точную временную длительность:
const { Duration } = require('@js-joda/core');
const duration = Duration.ofHours(5);
Duration подходит для времени, а Period —
для календарных сущностей.
Каждый тип в Js-joda имеет чёткую предметную область.
Поддерживает:
Не поддерживает:
Поддерживает:
Не поддерживает:
Instant представляет абсолютный момент времени в
UTC.
const { Instant } = require('@js-joda/core');
const instant = Instant.now();
console.log(instant.toString());
У Instant отсутствует концепция локального
календаря.
В обычном JavaScript легко спутать:
Js-joda делает такие ошибки заметными уже на уровне типов.
const { Instant, ZoneId } = require('@js-joda/core');
const instant = Instant.now();
const local = instant.atZone(
ZoneId.of('Asia/Almaty')
);
console.log(local.toString());
Преобразование выполняется только через явное указание зоны.
Строгая типизация особенно важна в бизнес-приложениях.
Дата рождения не должна содержать:
Правильный тип:
LocalDate
Онлайн-встреча требует:
Правильный тип:
ZonedDateTime
Для таймера нужен:
Duration
Для подписки используется:
Period
При использовании TypeScript преимущества Js-joda становятся ещё более заметными.
import { LocalDate } from '@js-joda/core';
function formatDate(date: LocalDate): string {
return date.toString();
}
Передача неправильного типа будет обнаружена компилятором.
formatDate("2025-01-01");
TypeScript сообщит о несовместимости типов.
const date = LocalDate.now();
date.plusDays(5);
Но:
const time = LocalTime.now();
time.plusDays(5);
Метод отсутствует.
Такой подход устраняет целый класс ошибок.
Js-joda избегает неявной магии.
const { LocalDate } = require('@js-joda/core');
const date = LocalDate.parse('2025-03-15');
Тип результата всегда предсказуем.
Для преобразования требуется временная зона.
const { ZoneOffset } = require('@js-joda/core');
const instant = dateTime.toInstant(
ZoneOffset.UTC
);
Без UTC-offset операция невозможна.
Часовые пояса — одна из главных причин ошибок в системах времени.
Js-joda делает работу с ними строго типизированной.
const zoned = ZonedDateTime.now(
ZoneId.of('Europe/Berlin')
);
Зона становится частью объекта.
const tokyo = zoned.withZoneSameInstant(
ZoneId.of('Asia/Tokyo')
);
Метод прямо указывает:
Многие библиотеки смешивают:
Но это не одно и то же.
Period.ofMonths(1)
Календарный месяц может содержать:
Duration.ofHours(24)
Точная длительность.
Во многих распределённых системах:
Instant идеально подходит для хранения.
const createdAt = Instant.now();
const display = createdAt.atZone(
ZoneId.of('Asia/Almaty')
);
Все основные типы используют стандартизированный формат.
LocalDate.parse('2025-03-15');
Instant.parse('2025-03-15T10:15:30Z');
В Js-joda отсутствует:
API остаётся:
По типу объекта сразу видно:
Большая часть ошибок времени возникает из-за:
Js-joda минимизирует такие ошибки архитектурно.
function schedule(dateTime) {}
Неочевидно, что ожидается.
function schedule(meeting: ZonedDateTime) {}
Семантика становится ясной сразу.
const date = new Date();
Объект одновременно содержит:
Модель неоднозначна.
Каждая сущность выделена в отдельный тип:
LocalDateLocalTimeLocalDateTimeZonedDateTimeInstantPeriodDurationЭто фундамент строгой архитектуры времени.
Js-joda строится вокруг идеи:
каждая временная сущность должна иметь собственный строгий тип.
Именно поэтому библиотека: