Библиотека Day.js построена вокруг минималистичного ядра, которое намеренно не перегружено функциональностью. Почти вся дополнительная логика подключается через систему расширений. Этот подход позволяет сохранять небольшой размер пакета и при этом гибко наращивать возможности за счёт плагинов.
Плагин в Day.js — это функция, которая получает объект экземпляра
Day.js и модифицирует его прототип или добавляет новые статические
возможности. Подключение осуществляется через метод
extend.
Ключевой принцип системы расширений:
ядро остаётся неизменным, вся функциональность добавляется извне
Подключение плагина выполняется через:
import dayjs from 'dayjs'
import plugin from 'dayjs/plugin/customParseFormat'
dayjs.extend(plugin)
Метод extend принимает два аргумента:
Внутри Day.js происходит вызов функции плагина с передачей конструктора и объекта Day.js:
plugin(dayjs, options)
Таким образом плагин получает доступ к:
Dayjs.prototypeПлагин представляет собой функцию с предсказуемой сигнатурой:
export default (option, dayjsClass, dayjsFactory) => {
// расширение прототипа
}
Однако на практике чаще используется упрощённая форма:
export default (o, c) => {
c.prototype.example = function () {
return this.add(1, 'day')
}
}
где:
o — options (если переданы через extend)c — класс Day.jsОсновная задача плагинов — расширение экземпляров Day.js.
Пример добавления метода форматирования:
export default (option, Dayjs) => {
Dayjs.prototype.toUpperFormat = function () {
return this.format('YYYY-MM-DD').toUpperCase()
}
}
Использование:
import dayjs from 'dayjs'
import upperFormat from './plugins/upperFormat'
dayjs.extend(upperFormat)
dayjs().toUpperFormat()
Особенности:
this внутри метода — экземпляр Day.jsformat,
add, subtract)Некоторые плагины не добавляют новые методы, а изменяют существующие:
export default (option, Dayjs) => {
const oldAdd = Dayjs.prototype.add
Dayjs.prototype.add = function (value, unit) {
const result = oldAdd.call(this, value, unit)
return result.startOf('day')
}
}
Такой подход требует осторожности:
Плагины могут расширять и сам конструктор:
export default (option, Dayjs) => {
Dayjs.isWeekday = function (date) {
const d = Dayjs(date)
return d.day() !== 0 && d.day() !== 6
}
}
Использование:
dayjs.isWeekday('2026-01-01')
Это полезно для:
extend поддерживает передачу опций:
dayjs.extend(plugin, { locale: 'ru' })
Внутри плагина:
export default (options, Dayjs) => {
const locale = options?.locale || 'en'
Dayjs.prototype.localeFormat = function () {
return this.locale(locale).format('LLLL')
}
}
Использование параметров позволяет:
Во многих плагинах важно определить, является ли объект экземпляром Day.js:
export default (o, Dayjs, dayjsFactory) => {
function isDayjsObject(obj) {
return dayjsFactory.isDayjs(obj)
}
}
Это предотвращает ошибки при работе с:
Плагины Day.js могут зависеть друг от друга. Например, один плагин может расширять поведение другого.
dayjs.extend(pluginA)
dayjs.extend(pluginB)
Порядок подключения имеет значение:
Пример зависимого плагина:
export default (o, Dayjs) => {
if (!Dayjs.prototype.isCustom) return
Dayjs.prototype.combined = function () {
return this.isCustom().format()
}
}
Хорошей практикой является предотвращение повторного расширения:
let installed = false
export default (o, Dayjs) => {
if (installed) return
installed = true
Dayjs.prototype.safeMethod = function () {
return this.add(1, 'hour')
}
}
Это важно для:
Некоторые расширения изменяют процесс создания дат:
export default (o, Dayjs, dayjsFactory) => {
const oldParse = dayjsFactory.parse
dayjsFactory.parse = function (date) {
if (typeof date === 'string' && date.includes('custom')) {
return new Date()
}
return oldParse(date)
}
}
Такие плагины:
Типизация улучшает надёжность расширений:
import { PluginFunc } from 'dayjs'
const myPlugin: PluginFunc = (option, Dayjs) => {
Dayjs.prototype.double = function () {
return this.add(1, 'day')
}
}
export default myPlugin
Дополнительно можно расширить интерфейсы:
declare module 'dayjs' {
interface Dayjs {
double(): Dayjs
}
}
Плагины проверяются как обычные модули:
import dayjs from 'dayjs'
import plugin from './plugin'
dayjs.extend(plugin)
test('custom method works', () => {
const result = dayjs('2020-01-01').double()
expect(result.date()).toBe(2)
})
Важно проверять:
Распространённые проблемы:
Пример проблемного кода:
Dayjs.prototype.add = function () {
return 'broken'
}
Такой подход полностью ломает библиотеку.
В крупных плагинах часто используется модульная структура:
plugin/
index.js
methods/
utils/
constants/
Главный файл объединяет части:
import { addFeature } from './methods/addFeature'
export default (o, Dayjs) => {
addFeature(Dayjs)
}
Такой подход упрощает: