В JavaScript обработка дат осложняется различиями региональных форматов. Одна и та же строка может интерпретироваться по-разному в зависимости от страны, языка и принятого стандарта записи даты.
Примеры:
04/05/2025
1 février 2025
понедельник, 7 октября 2024
Библиотека date-fns предоставляет механизм локализованного парсинга
через модуль локалей и функцию parse.
Локали импортируются отдельно. Это позволяет уменьшать размер итогового бандла приложения.
import { parse } from 'date-fns'
import { ru, enUS, fr, de } from 'date-fns/locale'
Каждая локаль содержит:
Сигнатура:
parse(dateString, formatString, referenceDate, options)
Аргументы:
| Аргумент | Назначение |
|---|---|
dateString |
строка с датой |
formatString |
шаблон разбора |
referenceDate |
базовая дата |
options |
дополнительные настройки |
Для локализованного парсинга используется параметр
locale.
import { parse } from 'date-fns'
import { ru } from 'date-fns/locale'
const result = parse(
'15 января 2025',
'd MMMM yyyy',
new Date(),
{ locale: ru }
)
console.log(result)
Шаблон:
| Токен | Значение |
|---|---|
d |
день месяца |
MMMM |
полное название месяца |
yyyy |
год |
const result = parse(
'10 фев 2025',
'd MMM yyyy',
new Date(),
{ locale: ru }
)
Здесь:
MMM — сокращенное название месяца;MMMM — полное название месяца.const result = parse(
'понедельник, 15 января 2025',
'EEEE, d MMMM yyyy',
new Date(),
{ locale: ru }
)
Токен EEEE соответствует полному названию дня
недели.
Сокращенные варианты:
| Токен | Пример |
|---|---|
E |
пн |
EE |
пн |
EEE |
пн |
EEEE |
понедельник |
import { enUS } from 'date-fns/locale'
const result = parse(
'January 15, 2025',
'MMMM d, yyyy',
new Date(),
{ locale: enUS }
)
import { fr } from 'date-fns/locale'
const result = parse(
'15 février 2025',
'd MMMM yyyy',
new Date(),
{ locale: fr }
)
Без передачи locale: fr парсинг завершится ошибкой.
import { de } from 'date-fns/locale'
const result = parse(
'15 März 2025',
'd MMMM yyyy',
new Date(),
{ locale: de }
)
parse требует базовую дату даже тогда, когда все части
даты присутствуют в строке.
parse(
'15 января 2025',
'd MMMM yyyy',
new Date(),
{ locale: ru }
)
Если часть данных отсутствует, значения берутся из
referenceDate.
Пример:
const result = parse(
'15 января',
'd MMMM',
new Date(2020, 5, 10),
{ locale: ru }
)
Результат:
2020-01-15
Год был взят из referenceDate.
const result = parse(
'15 января 2025 18:30',
'd MMMM yyyy HH:mm',
new Date(),
{ locale: ru }
)
Для английской локали часто используются 12-часовые форматы.
const result = parse(
'January 15, 2025 08:30 PM',
'MMMM d, yyyy hh:mm a',
new Date(),
{ locale: enUS }
)
Токены:
| Токен | Значение |
|---|---|
hh |
часы 01–12 |
HH |
часы 00–23 |
a |
AM/PM |
Date-fns поддерживает специальные локализованные токены.
parse(
'15.01.2025',
'P',
new Date(),
{ locale: ru }
)
Для разных локалей P означает разные шаблоны.
Например:
| Локаль | Интерпретация |
|---|---|
ru |
dd.MM.yyyy |
enUS |
MM/dd/yyyy |
de |
dd.MM.yyyy |
parse(
'15 янв. 2025 г.',
'PP',
new Date(),
{ locale: ru }
)
parse(
'15 января 2025 г.',
'PPP',
new Date(),
{ locale: ru }
)
parse(
'среда, 15 января 2025 г.',
'PPPP',
new Date(),
{ locale: ru }
)
Токены времени:
| Токен | Назначение |
|---|---|
p |
локализованное время |
pp |
расширенное время |
ppp |
время с дополнительными деталями |
Пример:
parse(
'15.01.2025, 18:45',
'Pp',
new Date(),
{ locale: ru }
)
parse(
'Wednesday, January 15th, 2025 at 8:30 PM',
'PPPP p',
new Date(),
{ locale: enUS }
)
Date.parse('15 января 2025')
Проблемы:
parse(
'15 января 2025',
'd MMMM yyyy',
new Date(),
{ locale: ru }
)
Преимущества:
После парсинга желательно проверять корректность даты.
import { isValid } from 'date-fns'
const result = parse(
'35 января 2025',
'd MMMM yyyy',
new Date(),
{ locale: ru }
)
console.log(isValid(result))
Результат:
false
parse(
'15 unknown 2025',
'd MMMM yyyy',
new Date(),
{ locale: enUS }
)
Результат:
Invalid Date
parse(
'2025-01-15',
'd MMMM yyyy',
new Date(),
{ locale: ru }
)
Шаблон не соответствует строке.
Date-fns не пытается «угадывать» формат.
Это принципиальное отличие от многих библиотек.
Строка:
15/01/2025
Не будет разобрана шаблоном:
MM/dd/yyyy
Локаль обычно не нужна для ISO-форматов.
parse(
'2025-01-15',
'yyyy-MM-dd',
new Date()
)
Но локаль можно комбинировать при смешанных форматах.
parse(
'15 janvier 2025 18:00',
'd MMMM yyyy HH:mm',
new Date(),
{ locale: fr }
)
Часто локаль выбирается на основе языка интерфейса.
import { ru, enUS, de } from 'date-fns/locale'
const locales = {
ru,
en: enUS,
de
}
const currentLocale = locales[userLanguage]
const result = parse(
input,
format,
new Date(),
{ locale: currentLocale }
)
При большом количестве языков локали загружаются динамически.
async function loadLocale(lang) {
switch (lang) {
case 'ru':
return (await import('date-fns/locale/ru')).ru
case 'fr':
return (await import('date-fns/locale/fr')).fr
default:
return (await import('date-fns/locale/en-US')).enUS
}
}
Типичный сценарий — ввод даты в форме.
function parseUserDate(value, locale) {
return parse(
value,
'P',
new Date(),
{ locale }
)
}
Преимущество:
Date-fns удобно интегрируется с i18n-системами:
Пример:
const localeMap = {
ru: ru,
en: enUS,
fr: fr
}
const locale = localeMap[i18n.language]
parse(
'15 janvier 2025',
'd MMMM yyyy',
new Date()
)
Французский месяц не распознается.
'M' // число месяца
'MMM' // краткое название
'MMMM' // полное название
Правильно:
yyyy
Неправильно:
YYYY
В Date-fns эти токены имеют разный смысл.
import { parse, isValid } from 'date-fns'
import { ru, enUS, fr } from 'date-fns/locale'
const localeMap = {
ru,
en: enUS,
fr
}
function parseLocalizedDate(value, lang) {
const locale = localeMap[lang]
const date = parse(
value,
'P',
new Date(),
{ locale }
)
if (!isValid(date)) {
throw new Error('Некорректная дата')
}
return date
}
Использование:
parseLocalizedDate('15.01.2025', 'ru')
parseLocalizedDate('01/15/2025', 'en')
parseLocalizedDate('15/01/2025', 'fr')
| Локаль | Пример |
|---|---|
ru |
15.01.2025 |
enUS |
01/15/2025 |
de |
15.01.2025 |
fr |
15/01/2025 |
Библиотека включает десятки локалей:
Каждая локаль импортируется отдельно:
import { ja } from 'date-fns/locale'
import { zhCN } from 'date-fns/locale'
import { uk } from 'date-fns/locale'
Особенности Date-fns:
При необходимости можно импортировать только нужные функции:
import parse from 'date-fns/parse'
import { Locale } from 'date-fns'
function parseDate(
value: string,
locale: Locale
): Date {
return parse(
value,
'P',
new Date(),
{ locale }
)
}
import { parse, isValid } from 'date-fns'
export function safeParse(
value,
format,
locale
) {
const result = parse(
value,
format,
new Date(),
{ locale }
)
if (!isValid(result)) {
return null
}
return result
}
Использование:
safeParse(
'15 января 2025',
'd MMMM yyyy',
ru
)