Формат JSON не содержит отдельного типа данных для даты. Любая дата в JSON представляется строкой. Наиболее распространённый формат — ISO 8601:
{
"createdAt": "2026-05-22T14:30:00.000Z"
}
После десериализации через JSON.parse() значение
остаётся строкой:
const json = `{
"createdAt": "2026-05-22T14:30:00.000Z"
}`
const data = JSON.parse(json)
console.log(typeof data.createdAt) // string
Для преобразования строки в объект Date библиотека
date-fns предоставляет набор инструментов для безопасного и
предсказуемого парсинга.
npm install date-fns
Импорт функций:
import { parseISO } from 'date-fns'
Основной инструмент для обработки JSON-дат —
parseISO().
import { parseISO } from 'date-fns'
const date = parseISO('2026-05-22T14:30:00.000Z')
console.log(date)
console.log(date instanceof Date)
Результат:
2026-05-22T14:30:00.000Z
true
Функция преобразует ISO-строку в полноценный объект
Date.
Многие разработчики используют:
const date = new Date('2026-05-22T14:30:00.000Z')
Однако parseISO() обладает рядом преимуществ:
parseISO() предназначена именно для ISO-форматов и
работает более стабильно между средами выполнения.
Код становится понятнее:
parseISO(value)
сразу показывает, что ожидается ISO-строка.
Функция хорошо интегрируется с остальными инструментами библиотеки:
import { parseISO, format, addDays } from 'date-fns'
const date = parseISO('2026-05-22T14:30:00.000Z')
console.log(format(date, 'dd.MM.yyyy'))
console.log(addDays(date, 7))
Типичный пример работы с REST API:
const response = await fetch('/api/users')
const users = await response.json()
Ответ сервера:
[
{
"id": 1,
"name": "Alex",
"createdAt": "2026-05-22T14:30:00.000Z"
}
]
Преобразование строковых дат:
import { parseISO } from 'date-fns'
const normalizedUsers = users.map(user => ({
...user,
createdAt: parseISO(user.createdAt)
}))
После этого можно безопасно использовать функции date-fns:
import { formatDistanceToNow } from 'date-fns'
console.log(
formatDistanceToNow(normalizedUsers[0].createdAt)
)
JSON-объекты часто содержат даты во вложенных полях.
Пример:
{
"user": {
"profile": {
"birthday": "1998-03-12"
}
}
}
Обработка:
import { parseISO } from 'date-fns'
const data = JSON.parse(json)
const birthday = parseISO(
data.user.profile.birthday
)
В крупных приложениях ручной вызов parseISO() для
каждого поля становится неудобным.
import { parseISO, isValid } from 'date-fns'
function reviveDates(obj) {
for (const key in obj) {
const value = obj[key]
if (typeof value === 'string') {
const parsed = parseISO(value)
if (isValid(parsed)) {
obj[key] = parsed
}
}
if (
typeof value === 'object' &&
value !== null
) {
reviveDates(value)
}
}
return obj
}
Использование:
const parsed = reviveDates(JSON.parse(json))
JSON.parse() поддерживает второй аргумент — функцию
reviver.
Это позволяет автоматически преобразовывать даты при десериализации.
import { parseISO, isValid } from 'date-fns'
const json = `{
"createdAt": "2026-05-22T14:30:00.000Z"
}`
const data = JSON.parse(json, (key, value) => {
if (typeof value === 'string') {
const parsed = parseISO(value)
if (isValid(parsed)) {
return parsed
}
}
return value
})
Теперь дата автоматически становится объектом Date.
Даже если строка похожа на дату, она может быть некорректной.
Пример:
parseISO('2026-99-99')
Для проверки используется isValid():
import { parseISO, isValid } from 'date-fns'
const date = parseISO('2026-99-99')
console.log(isValid(date))
Результат:
false
ISO-формат может содержать только дату:
2026-05-22
Обработка:
import { parseISO } from 'date-fns'
const date = parseISO('2026-05-22')
Важно понимать особенности timezone.
Строка:
2026-05-22T14:30:00.000Z
Суффикс Z означает UTC.
При выводе дата может автоматически конвертироваться в локальный timezone пользователя.
const date = parseISO('2026-05-22T14:30:00.000Z')
console.log(date.toString())
Строка:
2026-05-22T14:30:00
не содержит информации о часовом поясе.
Результат зависит от локальной среды выполнения.
parseISO('2026-05-22')
В некоторых часовых поясах отображение может давать предыдущий день.
Например:
Thu May 21 2026 21:00:00 GMT-0300
Это связано с внутренним хранением даты.
Если время не важно, рекомендуется:
Date.Пример:
import { parseISO, format } from 'date-fns'
const birthday = parseISO('1998-03-12')
console.log(
format(birthday, 'yyyy-MM-dd')
)
API часто возвращают null.
Пример:
{
"deletedAt": null
}
Безопасный парсинг:
import { parseISO } from 'date-fns'
const deletedAt = data.deletedAt
? parseISO(data.deletedAt)
: null
JSON:
{
"events": [
"2026-05-20T10:00:00Z",
"2026-05-21T12:00:00Z",
"2026-05-22T15:00:00Z"
]
}
Преобразование:
import { parseISO } from 'date-fns'
const dates = data.events.map(parseISO)
Некоторые API используют собственные форматы:
{
"createdAt": "22.05.2026 14:30"
}
parseISO() здесь не подойдёт.
Используется функция parse().
import { parse } from 'date-fns'
const date = parse(
'22.05.2026 14:30',
'dd.MM.yyyy HH:mm',
new Date()
)
Используется только для ISO-строк.
parseISO('2026-05-22T14:30:00Z')
Используется для произвольных шаблонов.
parse(
'22/05/2026',
'dd/MM/yyyy',
new Date()
)
2026-05-22T14:30:00.000Z
2026-05-22T14:30:00Z
2026-05-22
2026-05-22T14:30:00+03:00
Все эти варианты корректно обрабатываются
parseISO().
parseISO(undefined)
Результат:
Invalid Date
parseISO(null)
Также вернётся невалидная дата.
Ошибка:
format(parseISO(value), 'dd.MM.yyyy')
если value содержит мусорные данные.
Безопасный вариант:
import {
parseISO,
isValid,
format
} from 'date-fns'
const parsed = parseISO(value)
if (isValid(parsed)) {
console.log(
format(parsed, 'dd.MM.yyyy')
)
}
Простая проверка:
function isIsoDate(value) {
return /^\d{4}-\d{2}-\d{2}T/.test(value)
}
Использование:
import { parseISO } from 'date-fns'
const data = JSON.parse(json, (key, value) => {
if (
typeof value === 'string' &&
isIsoDate(value)
) {
return parseISO(value)
}
return value
})
type UserDto = {
id: number
createdAt: string
}
После преобразования:
type User = {
id: number
createdAt: Date
}
Функция маппинга:
import { parseISO } from 'date-fns'
function mapUser(dto: UserDto): User {
return {
...dto,
createdAt: parseISO(dto.createdAt)
}
}
При обработке тысяч объектов стоит учитывать:
parseISO() создаёт новые объекты
Date;Плохой вариант:
format(parseISO(date), 'dd.MM.yyyy')
format(parseISO(date), 'HH:mm')
format(parseISO(date), 'yyyy')
Лучше:
const parsed = parseISO(date)
format(parsed, 'dd.MM.yyyy')
format(parsed, 'HH:mm')
format(parsed, 'yyyy')
Даты при сохранении сериализуются в строки.
localStorage.setItem(
'user',
JSON.stringify(user)
)
После чтения:
const user = JSON.parse(
localStorage.getItem('user')
)
Поля дат снова становятся строками.
Восстановление:
import { parseISO } from 'date-fns'
user.createdAt = parseISO(user.createdAt)
GraphQL-серверы часто используют scalar DateTime.
Ответ:
{
"createdAt": "2026-05-22T14:30:00.000Z"
}
Клиентская нормализация:
import { parseISO } from 'date-fns'
const normalize = entity => ({
...entity,
createdAt: parseISO(entity.createdAt)
})
Наиболее распространённый сценарий:
import { parseISO, format } from 'date-fns'
const result = format(
parseISO('2026-05-22T14:30:00Z'),
'dd.MM.yyyy HH:mm'
)
console.log(result)
Результат:
22.05.2026 14:30
После обработки объект Date снова можно
сериализовать:
const json = JSON.stringify({
createdAt: new Date()
})
Результат:
{
"createdAt":"2026-05-22T14:30:00.000Z"
}
JavaScript автоматически вызывает toISOString().
import {
parseISO,
format
} from 'date-fns'
const response = `{
"id": 1,
"createdAt": "2026-05-22T14:30:00.000Z"
}`
const raw = JSON.parse(response)
const entity = {
...raw,
createdAt: parseISO(raw.createdAt)
}
console.log(
format(entity.createdAt, 'dd.MM.yyyy HH:mm')
)
import {
parseISO,
isValid
} from 'date-fns'
export function parseJsonDate(value) {
if (!value || typeof value !== 'string') {
return null
}
const parsed = parseISO(value)
return isValid(parsed)
? parsed
: null
}
Использование:
const createdAt = parseJsonDate(
response.createdAt
)
Такой подход: