Обработка ошибок парсинга

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

Ключевая особенность заключается в том, что корректность результата определяется не только входной строкой, но и полнотой подключённых CLDR-данных. При отсутствии необходимых данных результат парсинга может становиться null или сопровождаться ошибкой выполнения.

Типы ошибок парсинга

Ошибки в процессе преобразования строк в значения можно разделить на несколько категорий:

1. Ошибки формата

  • строка не соответствует ожидаемому шаблону локали
  • некорректные разделители
  • неожиданные символы

2. Ошибки локали

  • отсутствуют CLDR-данные для указанной локали
  • не загружены необходимые сегменты (numbers, dates, currencies)

3. Ошибки преобразования

  • невозможность интерпретации значения
  • переполнение или некорректный диапазон

4. Логические ошибки

  • неоднозначный формат (например, дата без указания порядка день/месяц)
  • конфликт настроек парсинга

Исключения и их обработка

Globalize не всегда генерирует исключения в классическом смысле. В большинстве API используется возвращаемое значение null или NaN, однако при некорректной конфигурации возможны ошибки на уровне выполнения JavaScript.

Типовой подход к обработке:

try {
  const number = Globalize("en").numberParser()(input);
  if (isNaN(number)) {
    throw new Error("Invalid number format");
  }
} catch (e) {
  // обработка ошибки парсинга
}

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

Строгий и нестрогий парсинг

Парсинг в Globalize может быть условно разделён на два режима поведения:

Нестрогий режим

  • допускает частичное соответствие формату
  • игнорирует лишние символы
  • может интерпретировать неоднозначные строки

Строгий режим

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

Пример различий:

const parser = Globalize("de").numberParser();

// нестрогий ввод
parser("1.234,5 EUR"); // может быть интерпретировано

// строгая проверка через предварительную валидацию
const pattern = Globalize("de").numberFormatter();

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

Ошибки чисел

Парсинг чисел наиболее чувствителен к локали из-за различий в форматировании:

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

Типичные ошибки:

const parser = Globalize("fr").numberParser();

parser("1,23,4"); // некорректная группировка
parser("12 34,56"); // неправильная структура групп
parser("12.34"); // неоднозначный формат для локали fr

При работе с числами важно учитывать:

  • необходимость предварительной очистки строки
  • удаление символов валют
  • нормализацию пробелов

Ошибки дат

Парсинг дат в Globalize зависит от локализованных шаблонов CLDR calendar.

Основные источники ошибок:

  • несоответствие формату даты локали
  • отсутствие времени при ожидаемом datetime формате
  • перепутанный порядок компонентов даты

Пример:

const parser = Globalize("en").dateParser();

parser("31/12/2025"); // ошибка для en (ожидается MM/DD/YYYY)
parser("2025-13-01"); // невозможный месяц

Особое внимание требуется при работе с неоднозначными форматами:

  • 01/02/2025 может интерпретироваться по-разному
  • отсутствие явного формата приводит к неопределённости

Для минимизации ошибок применяется явное указание шаблона через CLDR skeletons.

Ошибки валют

Парсинг валют включает дополнительные уровни сложности:

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

Пример проблемных случаев:

const parser = Globalize("en").currencyParser("USD");

parser("$1,234.56");
parser("1.234,56 $"); // для другой локали
parser("USD 100"); // зависит от настроек парсера

Частая проблема — несоответствие между кодом валюты и локалью, что приводит к некорректной интерпретации значения.

Проблемы CLDR данных

Критический источник ошибок — неполная загрузка CLDR:

  • отсутствуют сегменты main, supplemental
  • не загружены числа или календарь
  • некорректная инициализация Globalize.load

Последствия:

  • функции парсинга возвращают NaN
  • методы formatter/parser могут быть undefined
  • ошибки выполнения при вызове API

Пример корректной инициализации:

Globalize.load(
  require("cldr-data/main/en/numbers"),
  require("cldr-data/supplemental/likelySubtags")
);

Без этих данных поведение парсера становится непредсказуемым.

Практика обработки ошибок

Работа с парсингом требует многоуровневой проверки результата:

  1. Проверка входной строки
  2. Попытка парсинга
  3. Проверка результата (NaN, null)
  4. Фолбэк на альтернативный формат

Пример устойчивой обработки:

function safeParseNumber(globalize, value) {
  const parser = globalize.numberParser();
  const result = parser(value);

  if (typeof result !== "number" || isNaN(result)) {
    return null;
  }

  return result;
}

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

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

Паттерны безопасного парсинга

В прикладных системах используются устойчивые шаблоны обработки:

Паттерн предварительной нормализации

  • очистка строки перед парсингом
  • приведение к ожидаемому формату локали

Паттерн двойной проверки

  • первичный парсинг
  • повторная валидация форматтером

Паттерн fallback локали

  • попытка парсинга в основной локали
  • переход на en при ошибке
function parseWithFallback(globalize, value) {
  let result = globalize.numberParser()(value);

  if (isNaN(result)) {
    result = Globalize("en").numberParser()(value);
  }

  return isNaN(result) ? null : result;
}

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

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

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