Интеграция с Vue.js

Интеграция Date-fns с Vue.js строится вокруг принципа минимальной связности: библиотека не требует глобальной конфигурации и легко встраивается как в отдельные компоненты, так и в слой бизнес-логики.

Установка зависимости выполняется стандартным способом:

npm install date-fns

или

yarn add date-fns

Date-fns представляет собой набор чистых функций, что делает его удобным для использования в реактивной системе Vue без дополнительных обёрток.


Базовая архитектура интеграции

В Vue-проектах использование Date-fns обычно распределяется по трём уровням:

  • утилиты (helpers)
  • composables (Vue 3 Composition API)
  • глобальные фильтры/плагины (реже, в устаревших или гибридных подходах)

Основная идея — отделение форматирования и вычислений от шаблонов компонентов.


Форматирование дат в компонентах

Базовая функция форматирования импортируется напрямую:

import { format } from 'date-fns'

const formatted = format(new Date(), 'dd.MM.yyyy')

Использование в компоненте Vue:

<script setup>
import { format } from 'date-fns'

const now = new Date()
const formattedDate = format(now, 'dd.MM.yyyy HH:mm')
</script>

<template>
  <div>
    {{ formattedDate }}
  </div>
</template>

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


Реактивное форматирование через computed

При работе с динамическими датами применяется реактивная модель:

<script setup>
import { computed, ref } from 'vue'
import { format } from 'date-fns'

const timestamp = ref(Date.now())

const formatted = computed(() => {
  return format(new Date(timestamp.value), 'yyyy-MM-dd HH:mm:ss')
})
</script>

<template>
  <div>
    {{ formatted }}
  </div>
</template>

computed обеспечивает автоматическое обновление при изменении исходного значения.


Инкапсуляция логики через composables

Для масштабируемых приложений логика Date-fns выносится в composables.

// useDateFormat.js
import { computed } from 'vue'
import { format } from 'date-fns'

export function useDateFormat(dateRef, pattern = 'dd.MM.yyyy') {
  const formatted = computed(() => {
    if (!dateRef.value) return ''
    return format(new Date(dateRef.value), pattern)
  })

  return {
    formatted
  }
}

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

<script setup>
import { ref } from 'vue'
import { useDateFormat } from './useDateFormat'

const date = ref(Date.now())

const { formatted } = useDateFormat(date, 'dd.MM.yyyy HH:mm')
</script>

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


Работа с локалями

Date-fns поддерживает локализацию через отдельные модули:

import { format } from 'date-fns'
import { ru } from 'date-fns/locale'

Пример форматирования с локалью:

const formatted = format(new Date(), 'PPPP', { locale: ru })

В Vue-компоненте локаль часто передаётся как зависимость:

<script setup>
import { computed } from 'vue'
import { format } from 'date-fns'
import { ru } from 'date-fns/locale'

const date = new Date()

const formatted = computed(() => {
  return format(date, 'd MMMM yyyy', { locale: ru })
})
</script>

Подход позволяет централизовать поддержку мультиязычности.


Сравнение дат и реактивные состояния

Date-fns предоставляет функции сравнения, которые удобно применять в вычисляемых свойствах.

import { isAfter, isBefore } from 'date-fns'

Пример использования:

<script setup>
import { ref, computed } from 'vue'
import { isAfter } from 'date-fns'

const deadline = ref(new Date('2026-12-31'))
const now = ref(new Date())

const isExpired = computed(() => {
  return isAfter(now.value, deadline.value)
})
</script>

Такая модель часто используется для статусов событий, дедлайнов и уведомлений.


Работа с интервалами времени

Date-fns предоставляет функции для вычисления разницы:

import { differenceInDays, differenceInHours } from 'date-fns'

Пример:

<script setup>
import { computed, ref } from 'vue'
import { differenceInDays } from 'date-fns'

const start = ref(new Date('2026-01-01'))
const end = ref(new Date())

const days = computed(() => {
  return differenceInDays(end.value, start.value)
})
</script>

Такой подход применяется в аналитике, трекинге активности и отображении прогресса.


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

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

import { parse, format } from 'date-fns'

Пример:

<script setup>
import { ref } from 'vue'
import { parse, format } from 'date-fns'

const input = ref('01.05.2026')

const date = computed(() => {
  return parse(input.value, 'dd.MM.yyyy', new Date())
})

const formatted = computed(() => {
  return format(date.value, 'yyyy-MM-dd')
})
</script>

Такая схема используется в кастомных datepicker-компонентах.


Кеширование и оптимизация вычислений

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

Типичный подход — предварительное вычисление:

import { format } from 'date-fns'

function formatList(dates) {
  return dates.map(d => format(d, 'dd.MM.yyyy'))
}

В Vue это часто комбинируется с watch:

import { watch, ref } from 'vue'
import { format } from 'date-fns'

const rawDates = ref([])
const formatted = ref([])

watch(rawDates, (newVal) => {
  formatted.value = newVal.map(d => format(d, 'dd.MM.yyyy'))
})

Использование в глобальных утилитах проекта

В крупных проектах создаётся единый слой работы с датами:

// dateService.js
import { format, isValid } from 'date-fns'

export function safeFormat(date, pattern) {
  if (!isValid(date)) return ''
  return format(date, pattern)
}

Далее сервис подключается в компонентах без прямого импорта Date-fns.


Интеграция с Vue 3 реактивной моделью

Особенность Vue 3 заключается в глубокой реактивности объектов. При работе с Date-fns важно учитывать, что Date не является реактивным типом сам по себе.

Решение — хранение timestamp:

const date = ref(Date.now())

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

const formatted = computed(() => format(new Date(date.value), 'dd.MM.yyyy'))

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


Использование в SSR и Nuxt-подобных архитектурах

В серверном рендеринге форматирование дат выполняется на стороне сервера и должно быть детерминированным.

Особое внимание уделяется локали:

import { format } from 'date-fns'
import { ru } from 'date-fns/locale'

export function renderDate(date) {
  return format(date, 'dd MMMM yyyy', { locale: ru })
}

Результат сериализуется и передаётся клиенту без повторного вычисления.


Организация повторно используемых форматов

Для унификации отображения дат в интерфейсе создаются константы:

export const DATE_FORMATS = {
  short: 'dd.MM.yyyy',
  long: 'dd MMMM yyyy',
  time: 'HH:mm',
  full: 'dd.MM.yyyy HH:mm'
}

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

format(new Date(), DATE_FORMATS.full)

Такой подход снижает дублирование и повышает согласованность UI.


Обработка временных зон

Date-fns по умолчанию работает с локальным временем среды выполнения. Для управления временными зонами применяется дополнительный слой, например date-fns-tz.

import { format } from 'date-fns'
import { utcToZonedTime } from 'date-fns-tz'

const timeZone = 'Europe/Moscow'
const zonedDate = utcToZonedTime(new Date(), timeZone)

const formatted = format(zonedDate, 'dd.MM.yyyy HH:mm')

В Vue это часто инкапсулируется в composable:

export function useZonedDate(dateRef, zone) {
  const formatted = computed(() => {
    const zoned = utcToZonedTime(dateRef.value, zone)
    return format(zoned, 'dd.MM.yyyy HH:mm')
  })

  return { formatted }
}