Класс KJUR.jws.IntDate и работа со временем

В спецификациях JWT и JWS время всегда хранится как целое число, представляющее количество секунд, прошедших с 1 января 1970 года UTC (Unix Epoch). Такой формат упрощает сравнение, вычисления и передачу временных меток между системами.

В библиотеке Jsrsasign для этих целей используется класс KJUR.jws.IntDate, который предоставляет удобные методы для преобразования дат в числовой формат и обратно, а также для выполнения операций со временем без использования громоздких объектов Date в чистом виде.

Ключевая идея IntDate — работа исключительно с целыми секундами, а не миллисекундами, как это принято в стандартном JavaScript Date.


Базовое представление IntDate

IntDate — это числовое значение:

1714650000

Это количество секунд с начала эпохи Unix.

Для сравнения:

  • Date.now() возвращает миллисекунды
  • IntDate работает в секундах

Разница принципиальна, так как JWT стандарт (RFC 7519) требует именно секунды.


Основные методы KJUR.jws.IntDate

Преобразование текущего времени

KJUR.jws.IntDate.getNow()

Возвращает текущее время в формате IntDate.

Эквивалент:

Math.floor(Date.now() / 1000)

Используется при формировании JWT claims:

  • iat (issued at)
  • nbf (not before)
  • exp (expiration time)

Преобразование Date → IntDate

KJUR.jws.IntDate.getInt(date)

Преобразует объект Date в Unix time (секунды).

Пример:

const d = new Date("2026-01-01T00:00:00Z");
const intDate = KJUR.jws.IntDate.getInt(d);

Результат — целое число секунд.

Особенность реализации:

  • автоматически выполняется округление вниз
  • миллисекунды отбрасываются

Преобразование IntDate → Date

KJUR.jws.IntDate.getDate(intDate)

Преобразует числовое значение обратно в объект JavaScript Date.

Пример:

const date = KJUR.jws.IntDate.getDate(1714650000);

Это полезно при разборе JWT, когда необходимо отобразить временные поля в человекочитаемом виде.


Получение строки времени

KJUR.jws.IntDate.getString(intDate)

Возвращает строковое представление даты в UTC формате.

Пример результата:

"2026-05-02T12:00:00Z"

Используется для логирования и отладки JWT токенов.


Роль IntDate в JWT

В JSON Web Token временные поля строго определены:

  • iat — время выпуска токена
  • exp — время истечения
  • nbf — токен не действителен до этого времени

Пример payload:

const payload = {
  sub: "user123",
  iat: KJUR.jws.IntDate.getNow(),
  exp: KJUR.jws.IntDate.getNow() + 3600,
  nbf: KJUR.jws.IntDate.getNow()
};

Здесь IntDate обеспечивает корректный формат, совместимый с RFC.


Работа с временными интервалами

IntDate позволяет выполнять арифметику времени напрямую через секунды.

Добавление времени

Так как IntDate — это число, добавление выполняется обычной арифметикой:

const now = KJUR.jws.IntDate.getNow();
const inOneHour = now + 3600;
const inOneDay = now + 86400;

Это стандартный подход для JWT expiration logic.


Проверка актуальности токена

Типичный сценарий — сравнение текущего времени и exp:

function isTokenExpired(exp) {
  return KJUR.jws.IntDate.getNow() > exp;
}

Также учитывается возможный временной сдвиг (clock skew), когда серверы могут иметь небольшую разницу во времени.

Пример с запасом:

const skew = 60; // 60 секунд
const isExpired = KJUR.jws.IntDate.getNow() > (exp + skew);

Взаимодействие с JavaScript Date

Несмотря на наличие IntDate, в реальных приложениях часто требуется конвертация в стандартный Date.

Date → IntDate → Date цепочка

const date = new Date();
const intDate = KJUR.jws.IntDate.getInt(date);
const backToDate = KJUR.jws.IntDate.getDate(intDate);

Это полезно для:

  • сериализации JWT
  • хранения в базах данных
  • передачи между сервисами

Особенности точности

Важно учитывать:

  • IntDate всегда в секундах
  • миллисекунды теряются
  • все сравнения происходят на уровне секунд

Это может влиять на:

  • проверки истечения токена
  • синхронизацию систем
  • распределённые архитектуры

Использование в валидации JWT

При проверке токена библиотека Jsrsasign опирается на IntDate для сравнения claims:

  • iat — проверка времени выпуска
  • exp — проверка срока действия
  • nbf — проверка минимального времени начала действия

Пример логики:

const now = KJUR.jws.IntDate.getNow();

if (payload.nbf && now < payload.nbf) {
  throw new Error("Token not active yet");
}

if (payload.exp && now > payload.exp) {
  throw new Error("Token expired");
}

Практическая особенность генерации токенов

При создании JWT важно избегать ошибок:

  • использование Date.now() без деления на 1000
  • смешивание секунд и миллисекунд
  • отсутствие синхронизации времени

Правильный подход:

const iat = KJUR.jws.IntDate.getNow();
const exp = iat + 3600;

const token = {
  iat,
  exp
};

Поведение при разных временных зонах

IntDate всегда работает в UTC, что исключает:

  • влияние локальной временной зоны
  • DST (летнее время)
  • различия между серверами

Это делает формат устойчивым в распределённых системах.


Типичные ошибки при работе с IntDate

Использование миллисекунд вместо секунд

// ошибка
const exp = Date.now() + 3600;

Правильно:

const exp = KJUR.jws.IntDate.getNow() + 3600;

Сравнение Date и IntDate

new Date() > exp // некорректно

Правильно:

KJUR.jws.IntDate.getNow() > exp

Роль IntDate в архитектуре безопасности

Использование IntDate напрямую влияет на:

  • проверку срока действия токенов
  • предотвращение повторного использования JWT
  • синхронизацию авторизации между сервисами
  • защиту от replay-атак через временные ограничения

Модель работы основана на простом принципе: всё время — это число секунд, и оно сравнивается без дополнительной логики