Распознавание форматов дат

Библиотека Globalize предоставляет механизм интернационализации приложений на основе стандарта CLDR (Common Locale Data Repository). Одной из важных возможностей является распознавание строковых представлений дат с учётом локали пользователя.

Разные страны используют различные форматы:

Локаль Формат Пример
en-US MM/dd/yyyy 12/25/2025
en-GB dd/MM/yyyy 25/12/2025
de dd.MM.yyyy 25.12.2025
ja yyyy/MM/dd 2025/12/25

Без учёта локализации невозможно корректно определить, что означает строка 03/04/2025: 3 апреля или 4 марта.

Globalize решает эту проблему через локализованный парсинг дат.


Подключение модулей

Для работы с датами требуется модуль globalize/date.

const Globalize = require("globalize");

require("cldr-data").entireSupplemental();
require("cldr-data").entireMainFor("en", "ru");

Globalize.load(
    require("cldr-data/supplemental/likelySubtags.json"),
    require("cldr-data/main/en/ca-gregorian.json"),
    require("cldr-data/main/en/timeZoneNames.json"),
    require("cldr-data/main/en/numbers.json"),

    require("cldr-data/main/ru/ca-gregorian.json"),
    require("cldr-data/main/ru/timeZoneNames.json"),
    require("cldr-data/main/ru/numbers.json")
);

После загрузки данных можно создавать экземпляры локалей:

const en = new Globalize("en");
const ru = new Globalize("ru");

Метод parseDate

Основной метод распознавания дат:

globalize.parseDate(value, options)

Возвращает:

  • объект Date
  • либо null, если строка не соответствует формату

Простое распознавание даты

const ru = new Globalize("ru");

const result = ru.parseDate("25.12.2025");

console.log(result);

Результат:

2025-12-24T21:00:00.000Z

Объект хранится в UTC, поэтому отображение зависит от часового пояса среды выполнения.


Использование форматов

Короткий формат

const date = ru.parseDate("25.12.2025", {
    skeleton: "yMd"
});

Параметр skeleton определяет ожидаемую структуру даты.


Skeleton-форматы

Наиболее распространённые шаблоны:

Skeleton Значение
yMd дата
yMMMd дата с текстовым месяцем
yMEd дата + день недели
Hm часы и минуты
Hms время с секундами
GyMMMd дата с эрой

Распознавание даты с текстовым месяцем

const ru = new Globalize("ru");

const date = ru.parseDate("25 декабря 2025 г.", {
    skeleton: "yMMMd"
});

console.log(date);

Английские текстовые месяцы

const en = new Globalize("en");

const date = en.parseDate("December 25, 2025", {
    skeleton: "yMMMd"
});

console.log(date);

Автоматическое соответствие локали

Одна и та же строка может интерпретироваться по-разному.

const en = new Globalize("en");
const ru = new Globalize("ru");

console.log(
    en.parseDate("03/04/2025", {
        skeleton: "yMd"
    })
);

console.log(
    ru.parseDate("03.04.2025", {
        skeleton: "yMd"
    })
);

В английской локали:

March 4

В русской локали:

3 April

Строгая зависимость от формата

Globalize не пытается «угадывать» формат.

Если шаблон не совпадает, результатом будет null.

const ru = new Globalize("ru");

const date = ru.parseDate("2025-12-25", {
    skeleton: "yMd"
});

console.log(date);

Результат:

null

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

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

const parser = ru.dateParser({
    skeleton: "yMd"
});

console.log(parser("25.12.2025"));
console.log(parser("01.01.2026"));

Преимущества

  • выше производительность
  • отсутствие повторной компиляции шаблона
  • удобно при обработке больших объёмов данных

Внутренний принцип работы

Метод parseDate:

  1. получает locale-данные CLDR
  2. определяет допустимые шаблоны
  3. строит регулярные выражения
  4. извлекает компоненты даты
  5. формирует объект Date

Парсинг времени

const ru = new Globalize("ru");

const time = ru.parseDate("18:45", {
    skeleton: "Hm"
});

console.log(time);

Распознавание даты и времени

const ru = new Globalize("ru");

const result = ru.parseDate(
    "25.12.2025, 18:45:10",
    {
        skeleton: "yMdHms"
    }
);

console.log(result);

Работа с AM/PM

Американский формат времени:

const en = new Globalize("en");

const result = en.parseDate(
    "12/25/2025 10:30 PM",
    {
        skeleton: "yMdhm"
    }
);

console.log(result);

Парсинг дней недели

const en = new Globalize("en");

const result = en.parseDate(
    "Thu, Dec 25, 2025",
    {
        skeleton: "E yMMMd"
    }
);

console.log(result);

Проверка ошибок

Проверка на null

const parser = ru.dateParser({
    skeleton: "yMd"
});

const result = parser("неверная дата");

if (result === null) {
    console.log("Ошибка формата");
}

Валидация пользовательского ввода

function validateDate(value) {
    const parser = ru.dateParser({
        skeleton: "yMd"
    });

    return parser(value) !== null;
}

console.log(validateDate("25.12.2025"));
console.log(validateDate("99.99.9999"));

Проверка корректности календарной даты

Globalize валидирует реальные даты.

const result = ru.parseDate("31.02.2025", {
    skeleton: "yMd"
});

console.log(result);

Результат:

null

Парсинг ISO-строк

Globalize ориентирован на локализованные форматы, а не ISO.

Для ISO лучше использовать встроенный Jav * aScript:

const date = new Date("2025-12-25T10:30:00");

Либо:

Date.parse("2025-12-25T10:30:00");

Использование pattern вместо skeleton

Вместо сокращённого шаблона можно использовать точный pattern.

const parser = ru.dateParser({
    raw: "dd.MM.yyyy"
});

console.log(parser("25.12.2025"));

Отличие skeleton от raw

Skeleton

{
    skeleton: "yMd"
}
  • адаптируется под локаль
  • формат определяется автоматически

Raw

{
    raw: "dd.MM.yyyy"
}
  • строго фиксированный формат
  • без локализационных преобразований

Распознавание сокращённых месяцев

const ru = new Globalize("ru");

const result = ru.parseDate(
    "25 дек. 2025",
    {
        skeleton: "yMMMd"
    }
);

console.log(result);

Использование нескольких парсеров

Часто приложение поддерживает несколько форматов ввода.

const parsers = [
    ru.dateParser({ raw: "dd.MM.yyyy" }),
    ru.dateParser({ raw: "dd/MM/yyyy" }),
    ru.dateParser({ raw: "yyyy-MM-dd" })
];

function parse(value) {
    for (const parser of parsers) {
        const result = parser(value);

        if (result) {
            return result;
        }
    }

    return null;
}

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

const result = ru.parseDate(
    "12.2025",
    {
        raw: "MM.yyyy"
    }
);

console.log(result);

Парсинг неполных дат

Если отсутствуют некоторые компоненты, Globalize использует значения по умолчанию.

const result = ru.parseDate(
    "12.2025",
    {
        raw: "MM.yyyy"
    }
);

В большинстве случаев:

  • день → 1
  • время → 00:00:00

Поддержка различных календарей

Globalize использует CLDR и может работать с:

  • gregorian
  • buddhist
  • japanese
  • islamic

При этом требуется загрузка соответствующих CLDR-данных.


Распознавание японских эр

const ja = new Globalize("ja");

const result = ja.parseDate(
    "令和7年12月25日",
    {
        skeleton: "GyMd"
    }
);

console.log(result);

Производительность

Неэффективный вариант

for (const value of values) {
    const date = ru.parseDate(value, {
        skeleton: "yMd"
    });
}

Здесь шаблон создаётся заново при каждой итерации.


Оптимизированный вариант

const parser = ru.dateParser({
    skeleton: "yMd"
});

for (const value of values) {
    const date = parser(value);
}

Ограничения Globalize

Отсутствие fuzzy parsing

Библиотека не поддерживает:

сегодня
завтра
next friday
2 days ago

Globalize предназначен только для строгого форматного распознавания.


Отсутствие автоматического определения локали

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

Неверный пример:

globalize.parseDate("25 décembre 2025");

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


Комбинирование с Intl

Globalize часто применяется совместно со встроенным API Intl.

Форматирование через Intl

const formatter = new Intl.DateTimeFormat("ru-RU");

console.log(
    formatter.format(new Date())
);

Парсинг через Globalize

const parser = ru.dateParser({
    skeleton: "yMd"
});

console.log(
    parser("25.12.2025")
);

Типичная схема работы

Шаг 1 — ввод пользователя

25.12.2025

Шаг 2 — распознавание

const date = parser(input);

Шаг 3 — хранение

database.save(date.toISOString());

Шаг 4 — отображение

formatter.format(date);

Частые ошибки

Неполная загрузка CLDR

Ошибка:

E_MISSING_CLDR

Причина:

  • не загружены ca-gregorian
  • отсутствуют timeZoneNames
  • не подключены supplemental-данные

Несовпадение локали

const ru = new Globalize("ru");

ru.parseDate("12/25/2025", {
    skeleton: "yMd"
});

Результат:

null

Неверный skeleton

ru.parseDate("25.12.2025", {
    skeleton: "Hm"
});

Парсер ожидает время, а получает дату.


Практический пример формы регистрации

const parser = ru.dateParser({
    raw: "dd.MM.yyyy"
});

function handleBirthDate(value) {
    const date = parser(value);

    if (!date) {
        return {
            valid: false,
            message: "Неверный формат даты"
        };
    }

    return {
        valid: true,
        value: date
    };
}

Практический пример CSV-импорта

const parser = en.dateParser({
    raw: "MM/dd/yyyy"
});

for (const row of csvRows) {
    row.date = parser(row.dateString);
}

Сравнение с другими библиотеками

Библиотека Локализация Строгий парсинг CLDR
Globalize Да Да Да
Moment.js Частично Да Нет
Day.js Ограниченно Частично Нет
date-fns Через модули Да Нет

Когда Globalize особенно полезен

Наиболее подходящие сценарии:

  • международные корпоративные системы
  • мультиязычные CRM
  • финансовые приложения
  • ERP-системы
  • формы с локализованным вводом дат
  • приложения с поддержкой множества календарей

Архитектура dateParser

Внутренне dateParser() возвращает функцию:

function parser(value) {
    // parsing logic
}

Эта функция:

  • уже содержит скомпилированный шаблон
  • использует готовые regex-конструкции
  • минимизирует накладные расходы

Совместимость с Node.js и браузером

Globalize одинаково работает:

  • в браузере
  • в Node.js
  • в Electron
  • в SSR-приложениях

Однако CLDR-данные необходимо загружать отдельно для каждой среды.


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

const parser = globalize.dateParser({
    skeleton: "yMd"
});

function onChange(event) {
    const value = event.target.value;

    const date = parser(value);

    setDate(date);
}

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

methods: {
    parse(value) {
        return this.globalize.parseDate(
            value,
            { skeleton: "yMd" }
        );
    }
}

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

import Globalize from "globalize";

const globalize = new Globalize("ru");

const parser = globalize.dateParser({
    skeleton: "yMd"
});

const result: Date | null =
    parser("25.12.2025");

Рекомендации по организации кода

Создание централизованного сервиса

class DateService {
    constructor(locale) {
        this.globalize = new Globalize(locale);

        this.parser = this.globalize.dateParser({
            skeleton: "yMd"
        });
    }

    parse(value) {
        return this.parser(value);
    }
}

Кэширование парсеров

Создание парсера — дорогая операция.

Рекомендуется:

  • создавать парсер один раз
  • хранить экземпляры в singleton/service
  • переиспользовать между запросами

Безопасная обработка данных

Перед парсингом желательно:

value = value.trim();

Также полезно:

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

Разбор локализованных разделителей

В разных локалях используются:

Символ Пример
/ 12/25/2025
. 25.12.2025
- 2025-12-25
2025年12月25日

Globalize учитывает эти особенности автоматически через CLDR.