Прошедшее и будущее время

Globalize опирается на CLDR (Unicode Common Locale Data Repository), благодаря чему поддержка временных форматов — одна из наиболее точных и гибких частей библиотеки. Прошедшее и будущее время в контексте Globalize выражаются не через отдельные «магические» функции языка, а через комбинацию локализованных правил: относительное время, форматирование дат и языковые сообщения.

Работа с временными формами начинается с загрузки данных CLDR. Без них невозможно корректно вычислять формы прошедшего и будущего времени, поскольку именно CLDR содержит:

  • правила плюрализации;
  • локализованные названия единиц времени;
  • шаблоны относительных выражений;
  • форматы дат и времени.

Минимальный набор инициализации:

import Globalize from "globalize";
import cldr from "cldrjs";
import "globalize/dist/globalize-runtime";

// загрузка CLDR-данных (упрощённый пример)
Globalize.load(
  require("cldr-data/main/ru/ca-gregorian"),
  require("cldr-data/main/ru/numbers"),
  require("cldr-data/supplemental/likelySubtags"),
  require("cldr-data/supplemental/plurals"),
  require("cldr-data/supplemental/timeData")
);

Globalize.locale("ru");

После этого становятся доступны механизмы, которые различают «5 минут назад» и «через 5 минут» не только синтаксически, но и грамматически корректно.

Относительное время как основа прошедшего и будущего

Ключевой механизм — относительное время. Оно описывает интервал относительно текущего момента.

Прошедшее время

Прошедшее время формируется при отрицательных значениях интервалов:

const g = Globalize("ru");

g.formatRelativeTime(-5, "minute");
// "5 минут назад"

Смысловая модель:

  • отрицательное значение → прошедшее время;
  • единица измерения → minute, hour, day и т.д.;
  • CLDR определяет грамматику фразы.

Типовые единицы:

  • second
  • minute
  • hour
  • day
  • week
  • month
  • year

Пример масштабирования:

g.formatRelativeTime(-2, "hour");  // "2 часа назад"
g.formatRelativeTime(-1, "day");   // "1 день назад"
g.formatRelativeTime(-3, "month"); // "3 месяца назад"

Будущее время

Будущее время выражается положительными значениями:

g.formatRelativeTime(10, "minute");
// "через 10 минут"

Механика симметрична:

g.formatRelativeTime(2, "hour");  // "через 2 часа"
g.formatRelativeTime(7, "day");   // "через 7 дней"
g.formatRelativeTime(1, "year");  // "через 1 год"

Грамматическая корректность и правила плюрализации

Сложность прошедшего и будущего времени в локализации заключается не в вычислении интервала, а в выборе формы слова.

CLDR предоставляет правила плюрализации, которые Globalize применяет автоматически:

  • одна минута → «1 минута назад»
  • две минуты → «2 минуты назад»
  • пять минут → «5 минут назад»

Та же логика применяется в будущем времени:

  • «через 1 час»
  • «через 2 часа»
  • «через 5 часов»

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

g.formatRelativeTime(-1, "minute"); // "1 минута назад"
g.formatRelativeTime(-2, "minute"); // "2 минуты назад"
g.formatRelativeTime(-5, "minute"); // "5 минут назад"

Формирование контекста через форматирование дат

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

Прошедшее время через дату

const date = new Date(Date.now() - 3600 * 1000);

g.formatDate(date, { datetime: "medium" });

Результат зависит от локали, но логически отображает прошедший момент как фиксированную дату и время.

Будущее время через дату

const future = new Date(Date.now() + 2 * 24 * 3600 * 1000);

g.formatDate(future, { datetime: "medium" });

Это используется там, где относительное время теряет точность (например, расписания).

Гибридный подход: относительное и абсолютное время

В реальных интерфейсах применяется комбинированная логика:

  • короткие интервалы → относительное время;
  • большие интервалы → абсолютная дата.

Пример условной логики:

const diff = (date - Date.now()) / 1000;

if (Math.abs(diff) < 60 * 60 * 24) {
  g.formatRelativeTime(Math.round(diff / 60), "minute");
} else {
  g.formatDate(date, { datetime: "short" });
}

Такой подход делает отображение времени одновременно компактным и информативным.

Локализованные шаблоны времени

Globalize использует набор шаблонов, зависящих от языка:

  • «назад» для прошедшего времени;
  • «через» для будущего;
  • перестановка слов в некоторых языках;
  • различные формы числительных.

CLDR определяет эти конструкции, а Globalize подставляет значения.

Расширенные сценарии: кастомные единицы времени

В некоторых случаях стандартных единиц недостаточно. Тогда используется уровень сообщений:

Globalize.loadMessages({
  ru: {
    "time-past": "{0} назад",
    "time-future": "через {0}"
  }
});

Далее можно строить более сложные выражения:

const g = Globalize("ru");

const value = g.formatNumber(5);

g.messageFormatter("time-past")(value + " минут");

Хотя это уже выходит за рамки стандартного API относительного времени, механизм сообщений позволяет адаптировать логику под специфические требования интерфейса.

Поведение на границах интервалов

При переходах между единицами времени Globalize учитывает правила округления:

  • 59 секунд → «59 секунд назад»
  • 60 секунд → «1 минута назад»
  • 3600 секунд → «1 час назад»

Пример:

g.formatRelativeTime(-59, "second");
g.formatRelativeTime(-60, "second");

Фактическое отображение зависит от внутренней нормализации единиц.

Влияние локали на направление времени

В разных локалях меняется не только язык, но и структура выражения:

  • русский: «через 5 минут»
  • английский: “in 5 minutes”
  • некоторые языки могут менять порядок слов

Globalize не фиксирует синтаксис, а опирается на CLDR, что обеспечивает универсальность обработки прошедшего и будущего времени.

Интеграция с пользовательскими датами

При работе с API и данными серверов часто используются UNIX timestamp или ISO строки:

const g = Globalize("ru");

const pastDate = new Date("2026-05-25T10:00:00Z");

const diffMinutes = (pastDate - new Date()) / 60000;

g.formatRelativeTime(diffMinutes, "minute");

Такая модель позволяет унифицировать обработку временных данных независимо от источника.

Практика масштабирования интервалов

Для больших систем используется нормализация интервалов:

  • секунды → минуты
  • минуты → часы
  • часы → дни
  • дни → месяцы

Пример:

function formatTimeDiff(ms) {
  const minutes = ms / 60000;

  if (Math.abs(minutes) < 60) {
    return g.formatRelativeTime(minutes, "minute");
  }

  const hours = minutes / 60;

  if (Math.abs(hours) < 24) {
    return g.formatRelativeTime(hours, "hour");
  }

  const days = hours / 24;

  return g.formatRelativeTime(days, "day");
}

Такой подход обеспечивает предсказуемое отображение как прошедших, так и будущих событий.

Стабильность временных форматов в многоязычных системах

Globalize обеспечивает единый контракт:

  • вход: число + единица времени;
  • выход: локализованная строка;
  • поведение: детерминированное при одинаковых CLDR данных.

Это позволяет использовать одну и ту же логику для:

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