В Day.js преобразование даты в строку основано на строковых шаблонах, состоящих из токенов. Каждый токен отвечает за отдельный фрагмент даты: год, месяц, день, время, часовой пояс и другие компоненты. Кастомизация форматов строится не вокруг изменения внутреннего механизма библиотеки, а вокруг создания собственных шаблонов и уровней абстракции над ними.
Ключевой принцип заключается в том, что формат всегда задаётся строкой:
dayjs().format('YYYY-MM-DD HH:mm')
Однако в реальных проектах прямое использование строковых шаблонов быстро приводит к дублированию и снижению поддерживаемости. Поэтому возникает необходимость в создании кастомных форматов как уровня архитектуры приложения.
Day.js использует набор предопределённых токенов, которые комбинируются в произвольные шаблоны:
YYYY — полный годYY — последние две цифры годаMM — месяц с ведущим нулёмM — месяц без ведущего нуляDD — день месяцаHH — часы (24-часовой формат)mm — минутыss — секундыКастомный формат в Day.js — это всегда комбинация этих элементов:
dayjs().format('DD/MM/YYYY')
dayjs().format('YYYY год, MM месяц')
dayjs().format('HH:mm:ss | DD.MM.YYYY')
Форматирование не ограничено фиксированными шаблонами, что позволяет строить любые представления даты.
Одной из базовых техник кастомизации является вынесение строк форматов в отдельные структуры. Это устраняет магические строки и делает форматирование управляемым.
const DATE_FORMATS = {
ISO_DATE: 'YYYY-MM-DD',
READABLE_DATE: 'DD.MM.YYYY',
FULL_DATETIME: 'YYYY-MM-DD HH:mm:ss',
TIME_ONLY: 'HH:mm'
}
Использование:
dayjs().format(DATE_FORMATS.ISO_DATE)
dayjs().format(DATE_FORMATS.FULL_DATETIME)
Такой подход превращает форматирование в декларативную систему, где каждый формат имеет явное имя и назначение.
Следующий уровень абстракции — создание функций, инкапсулирующих форматирование. Это особенно полезно в доменно-ориентированном коде.
const formatDate = (date) => dayjs(date).format('DD.MM.YYYY')
const formatDateTime = (date) => dayjs(date).format('DD.MM.YYYY HH:mm')
const formatTime = (date) => dayjs(date).format('HH:mm')
Такой подход даёт несколько преимуществ:
Пример использования:
formatDate(order.createdAt)
formatDateTime(user.lastLoginAt)
Функции становятся фактическим слоем кастомных форматов, скрывающим детали Day.js.
Day.js позволяет расширять функциональность через
dayjs.fn, добавляя собственные методы.
import dayjs from 'dayjs'
dayjs.fn.formatDate = function () {
return this.format('DD.MM.YYYY')
}
dayjs.fn.formatDateTime = function () {
return this.format('DD.MM.YYYY HH:mm')
}
Использование:
dayjs().formatDate()
dayjs().formatDateTime()
Такой подход приближает работу с датами к объектной модели предметной области. Форматы становятся методами объекта даты, а не внешними строками.
Расширение прототипа особенно полезно в крупных кодовых базах, где важно унифицировать стиль работы с датами.
Day.js поддерживает локализацию через updateLocale, что
позволяет переопределять стандартные представления месяцев, дней недели
и относительных выражений.
import dayjs from 'dayjs'
import 'dayjs/locale/ru'
dayjs.locale('ru')
dayjs.updateLocale('ru', {
months: [
'Январь', 'Февраль', 'Март', 'Апрель',
'Май', 'Июнь', 'Июль', 'Август',
'Сентябрь', 'Октябрь', 'Ноябрь', 'Декабрь'
],
weekdays: [
'Воскресенье', 'Понедельник', 'Вторник',
'Среда', 'Четверг', 'Пятница', 'Суббота'
]
})
После этого форматы, использующие текстовые токены, начинают возвращать значения в соответствии с заданной локалью:
dayjs().format('D MMMM YYYY')
Здесь кастомизация происходит на уровне языка отображения, а не структуры формата.
Некоторые форматы становятся доступны только после подключения
дополнительных плагинов, например advancedFormat.
import advancedFormat from 'dayjs/plugin/advancedFormat'
dayjs.extend(advancedFormat)
После расширения появляются дополнительные токены:
Qo — кварталDo — день месяца с порядковым суффиксомgggg — ISO-неделя годаПример:
dayjs().format('Do MMMM YYYY')
Такая система расширяет возможности кастомных форматов без изменения ядра библиотеки.
В сложных системах форматы часто комбинируются в зависимости от контекста. Вместо одного фиксированного шаблона используются составные правила.
const buildFormat = ({ date, withTime }) => {
if (withTime) {
return dayjs(date).format('DD.MM.YYYY HH:mm')
}
return dayjs(date).format('DD.MM.YYYY')
}
Другой вариант — словарь условий:
const FORMAT_BY_TYPE = {
short: 'DD.MM.YYYY',
long: 'DD MMMM YYYY',
datetime: 'DD.MM.YYYY HH:mm:ss'
}
const formatByType = (date, type) => {
return dayjs(date).format(FORMAT_BY_TYPE[type])
}
Композиция форматов позволяет адаптировать отображение даты под сценарий использования без изменения логики библиотеки.
Day.js не ограничивает динамическую сборку строк формата. Шаблон может быть сформирован во время выполнения:
const getFormat = (showSeconds) => {
let base = 'HH:mm'
if (showSeconds) {
base += ':ss'
}
return base
}
dayjs().format(getFormat(true))
Также возможно использование параметрических форматов:
const formatDate = (date, separator = '.') => {
const format = `DD${separator}MM${separator}YYYY`
return dayjs(date).format(format)
}
Такая гибкость делает систему форматов полностью динамической.
В масштабируемых приложениях форматирование даты рассматривается как отдельный слой. Day.js используется только как движок преобразования, а вся логика форматов выносится наружу.
const DatePresenter = {
iso: (d) => dayjs(d).format('YYYY-MM-DD'),
ui: (d) => dayjs(d).format('DD.MM.YYYY'),
full: (d) => dayjs(d).format('DD.MM.YYYY HH:mm:ss')
}
Использование:
DatePresenter.ui(invoice.date)
DatePresenter.full(event.timestamp)
Такой подход снижает связанность кода с конкретной библиотекой и упрощает замену форматтера при необходимости.
При создании кастомных форматов важно учитывать несколько ограничений архитектуры:
Неправильно организованные кастомные форматы приводят к расхождению отображения дат в разных частях системы, что особенно критично в интерфейсах с высокой плотностью информации.
В крупных системах форматы часто выносятся в отдельный модуль, который становится единственным источником истины:
export const FORMATS = {
API: 'YYYY-MM-DDTHH:mm:ssZ',
USER: 'DD.MM.YYYY',
LOG: 'YYYY-MM-DD HH:mm:ss',
TIME: 'HH:mm'
}
Такой модуль используется во всех слоях приложения — от UI до API-интеграций, обеспечивая согласованность представления данных.
Наиболее зрелая форма кастомных форматов заключается в полной изоляции Day.js за собственным API:
import dayjs from 'dayjs'
const DateService = {
format(date, type = 'USER') {
const formats = {
USER: 'DD.MM.YYYY',
API: 'YYYY-MM-DDTHH:mm:ssZ',
TIME: 'HH:mm'
}
return dayjs(date).format(formats[type])
}
}
Использование:
DateService.format(order.createdAt, 'USER')
DateService.format(new Date(), 'TIME')
В этой модели Day.js становится внутренним механизмом, а кастомные форматы — частью бизнес-логики приложения, а не просто строковыми шаблонами.