Юлианский календарь

Юлианский календарь — историческая календарная система, введённая Юлием Цезарем в 45 году до н. э. В отличие от современного григорианского календаря, юлианский использует более простое правило високосных лет: каждый четвёртый год считается високосным без исключений. Из-за накопления ошибки в продолжительности года юлианский календарь постепенно смещается относительно астрономического времени.

Библиотека Luxon напрямую не предоставляет полноценного API для работы с юлианским календарём как альтернативной календарной системой. Однако Luxon поддерживает:

  • преобразование дат;
  • вычисления между историческими датами;
  • работу с юлианскими днями (Julian Day);
  • отображение дат в разных локалях;
  • операции с временными зонами;
  • хранение и обработку исторических временных меток.

Понимание различий между юлианским календарём, юлианским днём и григорианским календарём особенно важно при разработке:

  • астрономических систем;
  • архивных приложений;
  • исторических баз данных;
  • научного ПО;
  • систем обработки старых документов.

Разница между юлианским календарём и Julian Day

В программировании часто путают два разных понятия:

Термин Описание
Юлианский календарь Историческая календарная система
Julian Day (JD) Непрерывный счёт дней, используемый в астрономии

Luxon работает именно с Julian Day Number, а не с юлианским календарём как системой отображения дат.


Работа с Julian Day в Luxon

Класс DateTime содержит методы для преобразования даты в юлианский день.

Получение Julian Day

import { DateTime } from "luxon";

const date = DateTime.local(2025, 5, 24);

console.log(date.toJulianDay());

Результат:

2460820.5

Значение представляет количество дней, прошедших с начала юлианской эпохи.


Что такое юлианский день

Юлианский день — это непрерывная шкала времени, используемая в астрономии.

Начальная точка:

  • 1 января 4713 года до н. э.
  • 12:00 UTC

Это позволяет выполнять вычисления дат без учёта:

  • календарных реформ;
  • високосных правил;
  • смены месяцев;
  • локальных календарей.

Преобразование Julian Day обратно в DateTime

Luxon поддерживает создание объекта DateTime из юлианского дня.

import { DateTime } from "luxon";

const dt = DateTime.fromJulianDay(2460820.5);

console.log(dt.toISO());

Результат:

2025-05-24T00:00:00.000Z

Точность Julian Day

Julian Day хранится как число с плавающей точкой.

Целая часть:

  • количество дней.

Дробная часть:

  • время суток.

Пример:

import { DateTime } from "luxon";

const dt = DateTime.utc(2025, 5, 24, 18, 0);

console.log(dt.toJulianDay());

Результат:

2460821.25

Здесь:

  • .25 соответствует 6 часам после полудня UTC.

Исторические даты и проблемы календарей

Главная сложность при работе с историческими датами — календарная реформа.

Переход с юлианского на григорианский календарь

В разных странах переход происходил в разное время:

Страна Год перехода
Италия 1582
Франция 1582
Англия 1752
Россия 1918

Luxon использует проleptic Gregorian calendar — расширенный григорианский календарь на все даты.

Это означает:

import { DateTime } from "luxon";

const dt = DateTime.fromISO("1500-01-01");

console.log(dt.toISODate());

Дата интерпретируется как григорианская, хотя исторически в тот период использовался юлианский календарь.


Проблема исторической достоверности

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

Например:

DateTime.fromISO("1000-01-01")

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

Для исторически точных вычислений обычно используются:

  • специализированные астрономические библиотеки;
  • ICU-календари;
  • Temporal API с календарями;
  • внешние преобразования.

Разница между юлианской и григорианской датой

Разница между календарями постепенно увеличивается.

Период Разница
1582 10 дней
1700 11 дней
1800 12 дней
1900 13 дней
2100 14 дней

Ручное преобразование юлианской даты

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

Пример

Дата:

1 января 1900 года (юлианский)

Соответствует:

13 января 1900 года (григорианский)

В Luxon это можно реализовать вручную:

import { DateTime } from "luxon";

const julianDate = DateTime.fromISO("1900-01-01");

const gregorianEquivalent = julianDate.plus({ days: 13 });

console.log(gregorianEquivalent.toISODate());

Создание функции преобразования

import { DateTime } from "luxon";

function julianToGregorian(date, offsetDays) {
  return date.plus({ days: offsetDays });
}

const julian = DateTime.fromISO("1900-01-01");

const gregorian = julianToGregorian(julian, 13);

console.log(gregorian.toISODate());

Автоматический расчёт смещения

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

function getJulianOffset(year) {
  if (year >= 2100) return 14;
  if (year >= 1900) return 13;
  if (year >= 1800) return 12;
  if (year >= 1700) return 11;
  return 10;
}

Использование:

import { DateTime } from "luxon";

const year = 1850;

const offset = getJulianOffset(year);

const julian = DateTime.fromObject({
  year,
  month: 5,
  day: 1
});

const gregorian = julian.plus({
  days: offset
});

console.log(gregorian.toISODate());

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

Luxon поддерживает очень ранние даты.

import { DateTime } from "luxon";

const ancient = DateTime.fromObject({
  year: -44,
  month: 3,
  day: 15
});

console.log(ancient.toISODate());

Результат:

-0044-03-15

Это дата убийства Юлия Цезаря.


Особенности отрицательных лет

Luxon использует астрономическую нумерацию лет:

Исторический год Luxon
1 до н. э. 0
2 до н. э. -1
44 до н. э. -43

Это важно учитывать при исторических вычислениях.


Julian Day и временные зоны

Юлианский день зависит от UTC.

Пример:

import { DateTime } from "luxon";

const local = DateTime.local();
const utc = local.toUTC();

console.log(local.toJulianDay());
console.log(utc.toJulianDay());

При преобразовании временной зоны меняется дробная часть числа.


Использование UTC для астрономических вычислений

Для корректных вычислений Julian Day рекомендуется использовать UTC.

import { DateTime } from "luxon";

const dt = DateTime.utc(2025, 5, 24, 0, 0);

console.log(dt.toJulianDay());

Модифицированный юлианский день

В научных системах часто используется MJD (Modified Julian Day).

Формула:

MJD = JD - 2400000.5

Пример:

import { DateTime } from "luxon";

const jd = DateTime.utc().toJulianDay();

const mjd = jd - 2400000.5;

console.log(mjd);

Вычисление интервалов через Julian Day

Julian Day удобен для точных расчётов промежутков.

import { DateTime } from "luxon";

const start = DateTime.utc(2025, 1, 1);
const end = DateTime.utc(2025, 12, 31);

const diff =
  end.toJulianDay() - start.toJulianDay();

console.log(diff);

Сравнение исторических дат

import { DateTime } from "luxon";

const d1 = DateTime.fromISO("1582-10-04");
const d2 = DateTime.fromISO("1582-10-15");

console.log(d2.diff(d1, "days").days);

Luxon считает даты непрерывно без пропуска календарной реформы.


Астрономические приложения

Julian Day широко применяется:

  • в телескопах;
  • эфемеридах;
  • космической навигации;
  • спутниковых системах;
  • моделировании орбит.

Luxon удобен как вспомогательный инструмент обработки временных данных.


Ограничения Luxon при работе с юлианским календарём

Отсутствие альтернативных календарей

Luxon не поддерживает:

  • calendar: "julian"
  • автоматическое преобразование календарей;
  • локализованные исторические календари.

Отсутствие встроенной реформы календаря

Нет автоматического учёта:

  • переходов между календарями;
  • региональных особенностей;
  • исторических исключений.

Нет поддержки исторической хронологии

Luxon ориентирован на современные вычисления времени, а не на академическую хронологию.


Интеграция с другими библиотеками

Для сложной работы с юлианским календарём Luxon часто комбинируют с:

  • astronomical algorithms;
  • js-joda;
  • Temporal polyfill;
  • moment-hijri;
  • custom conversion layers.

Практический пример: конвертер календарей

import { DateTime } from "luxon";

function convertJulianToGregorian(
  year,
  month,
  day
) {
  const offset = getJulianOffset(year);

  return DateTime.fromObject({
    year,
    month,
    day
  }).plus({
    days: offset
  });
}

function getJulianOffset(year) {
  if (year >= 2100) return 14;
  if (year >= 1900) return 13;
  if (year >= 1800) return 12;
  if (year >= 1700) return 11;
  return 10;
}

const result =
  convertJulianToGregorian(1900, 1, 1);

console.log(result.toISODate());

Проверка високосного года в юлианском календаре

Правило юлианского календаря:

year = 0

Реализация:

function isJulianLeapYear(year) {
  return year % 4 === 0;
}

console.log(isJulianLeapYear(1900));

Результат:

true

В григорианском календаре 1900 год не является високосным.


Сравнение правил високосного года

Юлианский календарь

year % 4 === 0

Григорианский календарь

(year % 4 === 0 && year % 100 !== 0)
|| year % 400 === 0

Ошибка юлианского календаря

Средняя длина юлианского года:

365.25

Реальная длина тропического года:

365.2422

Разница:

365.25 - 365.2422 = 0.0078

Из-за этого календарь смещается примерно на 1 день каждые 128 лет.


Использование Luxon в исторических системах

Типичные сценарии:

Архивные системы

const archivedDate =
  DateTime.fromISO("1789-07-14");

Исторические базы данных

const battleDate =
  DateTime.fromObject({
    year: 1242,
    month: 4,
    day: 5
  });

Астрономические вычисления

const jd =
  DateTime.utc().toJulianDay();

Проверка корректности преобразований

При работе с историческими датами рекомендуется:

  • хранить исходную календарную систему;
  • сохранять UTC-время отдельно;
  • документировать источник даты;
  • учитывать региональную реформу календаря;
  • избегать автоматических преобразований без проверки.

Производительность вычислений Julian Day

Операции с юлианским днём выполняются быстро, поскольку основаны на арифметике чисел.

import { DateTime } from "luxon";

const jd1 = DateTime.utc(2000, 1, 1)
  .toJulianDay();

const jd2 = DateTime.utc(2025, 1, 1)
  .toJulianDay();

console.log(jd2 - jd1);

Такой подход особенно эффективен в:

  • научных вычислениях;
  • симуляциях;
  • обработке эфемерид;
  • астрономических моделях;
  • системах временных рядов.