Модификация существующих локалей

В Day.js локаль представляет собой объект конфигурации, который определяет правила форматирования дат и времени: названия месяцев и дней недели, правила склонений, формат относительного времени, порядок недели и дополнительные языковые особенности. В отличие от некоторых библиотек, Day.js не создает жестких копий локалей при каждом изменении — используется модель расширения и частичного переопределения.

Каждая локаль хранится под строковым идентификатором ('en', 'ru', 'de' и т.д.) и может быть изменена во время выполнения программы. Это делает возможной тонкую настройку поведения без необходимости создания новой локали с нуля.


Структура локали Day.js

Локаль в Day.js представляет собой объект со следующими ключевыми компонентами:

  • months — названия месяцев
  • monthsShort — сокращенные названия месяцев
  • weekdays — дни недели
  • weekdaysShort — сокращенные дни недели
  • weekdaysMin — минимальные обозначения дней
  • longDateFormat — шаблоны форматирования дат
  • relativeTime — правила отображения относительного времени
  • ordinal — функция формирования порядковых чисел
  • weekStart — первый день недели
  • formats (в некоторых локалях через плагины или расширения)

Эти поля формируют основу поведения форматирования и парсинга.


Механизм модификации локалей через updateLocale

Основной способ изменения уже существующей локали — использование метода updateLocale.

Метод работает по принципу глубокого частичного слияния: переданные поля переопределяют только указанные части локали, не затрагивая остальные.

Базовый синтаксис

dayjs.updateLocale('ru', {
  months: ['Янв', 'Фев', 'Мар', 'Апр', 'Май', 'Июн',
           'Июл', 'Авг', 'Сен', 'Окт', 'Ноя', 'Дек']
})

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


Переопределение названий месяцев и дней недели

Частый сценарий — адаптация локали под специфический формат вывода (например, сокращения для UI или нестандартные подписи).

Изменение месяцев

dayjs.updateLocale('en', {
  months: [
    'Jan_UX', 'Feb_UX', 'Mar_UX', 'Apr_UX',
    'May_UX', 'Jun_UX', 'Jul_UX', 'Aug_UX',
    'Sep_UX', 'Oct_UX', 'Nov_UX', 'Dec_UX'
  ]
})

Изменение дней недели

dayjs.updateLocale('en', {
  weekdays: [
    'Sunday*', 'Monday*', 'Tuesday*',
    'Wednesday*', 'Thursday*',
    'Friday*', 'Saturday*'
  ]
})

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


Управление форматами даты (longDateFormat)

longDateFormat определяет, как интерпретируются стандартные токены форматирования:

  • LT — время
  • LTS — время с секундами
  • L — дата
  • LL — расширенная дата
  • LLL — дата и время
  • LLLL — полное текстовое представление

Пример модификации форматов

dayjs.updateLocale('en', {
  longDateFormat: {
    LT: 'HH:mm',
    LTS: 'HH:mm:ss',
    L: 'YYYY/MM/DD',
    LL: 'D MMMM YYYY',
    LLL: 'D MMMM YYYY HH:mm',
    LLLL: 'dddd, D MMMM YYYY HH:mm'
  }
})

Изменение этих значений напрямую влияет на результат методов .format() при использовании соответствующих токенов.


Настройка относительного времени (relativeTime)

Один из наиболее важных блоков локали — relativeTime. Он определяет, как Day.js отображает разницу между датами.

Структура включает ключи:

  • future
  • past
  • s
  • m
  • mm
  • h
  • hh
  • d
  • dd
  • M
  • MM
  • y
  • yy

Пример модификации

dayjs.updateLocale('en', {
  relativeTime: {
    future: 'через %s',
    past: '%s назад',
    s: 'несколько секунд',
    m: 'минута',
    mm: '%d минут',
    h: 'час',
    hh: '%d часов',
    d: 'день',
    dd: '%d дней',
    M: 'месяц',
    MM: '%d месяцев',
    y: 'год',
    yy: '%d лет'
  }
})

Формат %d используется как плейсхолдер для числового значения.


Функция ordinal и порядковые числительные

ordinal отвечает за преобразование чисел в порядковые формы (1st, 2nd, 3rd и т.д.).

Пример переопределения

dayjs.updateLocale('en', {
  ordinal: function (n) {
    return `${n}-й`
  }
})

Этот механизм особенно важен для языков с развитой системой склонений.


Изменение первого дня недели

Поле weekStart управляет началом недели:

  • 0 — воскресенье
  • 1 — понедельник
  • 6 — суббота

Пример

dayjs.updateLocale('en', {
  weekStart: 1
})

Это влияет на работу календарных вычислений, таких как .startOf('week').


Переопределение частями и поведение merge

Механизм updateLocale не заменяет объект целиком. Он выполняет частичное слияние:

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

Пример частичного обновления

dayjs.updateLocale('en', {
  relativeTime: {
    mm: '%d minutes (custom)'
  }
})

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


Многократные модификации одной локали

Локаль может быть изменена несколько раз подряд. Каждое последующее изменение накладывается поверх предыдущего состояния.

dayjs.updateLocale('en', {
  monthsShort: ['J', 'F', 'M']
})

dayjs.updateLocale('en', {
  weekdaysMin: ['Su', 'Mo', 'Tu']
})

Результирующая локаль объединяет оба изменения.


Переключение локали и влияние на модификации

Важно различать:

  • активную локаль (dayjs.locale('ru'))
  • зарегистрированную локаль (updateLocale)

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

dayjs.locale('ru')
dayjs.updateLocale('ru', {
  months: ['Янв', 'Фев']
})

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


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

Для анализа текущей локали применяется плагин localeData.

import localeData from 'dayjs/plugin/localeData'
dayjs.extend(localeData)

Позволяет получить:

dayjs.months()
dayjs.weekdays()
dayjs.weekdaysMin()
dayjs.weekdaysShort()
dayjs.localeData().firstDayOfWeek()

Это полезно для проверки результатов updateLocale.


Практика глубокого переопределения локали

Иногда требуется полная кастомизация без создания новой локали.

Пример комплексной модификации

dayjs.updateLocale('en', {
  months: [
    'Month1', 'Month2', 'Month3', 'Month4',
    'Month5', 'Month6', 'Month7', 'Month8',
    'Month9', 'Month10', 'Month11', 'Month12'
  ],
  weekdays: [
    'SunX', 'MonX', 'TueX', 'WedX',
    'ThuX', 'FriX', 'SatX'
  ],
  longDateFormat: {
    L: 'DD.MM.YYYY',
    LL: 'D MMM YYYY',
    LLL: 'D MMM YYYY HH:mm'
  },
  relativeTime: {
    future: '+%s',
    past: '-%s',
    s: '<1m',
    m: '1m',
    mm: '%dm',
    h: '1h',
    hh: '%dh',
    d: '1d',
    dd: '%dd',
    M: '1mo',
    MM: '%dmo',
    y: '1y',
    yy: '%dy'
  }
})

Такая конфигурация фактически превращает локаль в доменно-специфичный формат отображения.


Особенности работы с массивами в локалях

При модификации массивов важно учитывать, что Day.js не объединяет массивы, а полностью заменяет их.

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

  • нельзя частично изменить один месяц
  • необходимо переопределять весь массив целиком
  • пропущенные элементы приведут к некорректному отображению

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

Если локаль не зарегистрирована, updateLocale может не создать её автоматически. В таком случае необходимо сначала импортировать или определить локаль:

import 'dayjs/locale/ru'

После этого можно безопасно применять модификации.


Влияние модификаций на производительность и кеширование

Day.js хранит локали в памяти. Повторные вызовы updateLocale:

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

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


Типичные ошибки при модификации локалей

  • частичное заполнение массивов месяцев или дней
  • переопределение relativeTime без всех ключей
  • ожидание deep-merge для массивов
  • изменение локали после форматирования с кешированием результата
  • конфликт нескольких updateLocale в разных модулях приложения

Каждая из этих ситуаций приводит к непредсказуемому выводу дат при форматировании.