Строгий парсинг с parseISO

Функция parseISO из библиотеки date-fns предназначена для строгого разбора строк в формате ISO 8601 и преобразования их в объект Date.

В отличие от стандартного конструктора Date, который может по-разному интерпретировать строки в зависимости от браузера и окружения, parseISO обеспечивает предсказуемое поведение и корректную обработку ISO-дат.

import { parseISO } from 'date-fns'

const date = parseISO('2025-03-15')

console.log(date)

Результат:

2025-03-15T00:00:00.000Z

Почему parseISO предпочтительнее new Date()

Стандартный JavaScript-парсер дат обладает рядом проблем:

new Date('2025-03-15')

В разных средах:

  • дата может считаться UTC;
  • дата может интерпретироваться как локальная;
  • возможны различия между браузерами;
  • не-ISO строки могут разбираться непредсказуемо.

parseISO решает эти проблемы:

import { parseISO } from 'date-fns'

const date = parseISO('2025-03-15')

Основные преимущества:

  • строгая поддержка ISO 8601;
  • единое поведение во всех окружениях;
  • предсказуемая работа с часовыми поясами;
  • защита от неоднозначных форматов.

Форматы ISO 8601

parseISO поддерживает различные варианты ISO-строк.

Полная дата

parseISO('2025-03-15')

Дата и время

parseISO('2025-03-15T14:30:00')

UTC-время

parseISO('2025-03-15T14:30:00Z')

Суффикс Z означает UTC.


Часовой пояс

parseISO('2025-03-15T14:30:00+05:00')

Миллисекунды

parseISO('2025-03-15T14:30:00.123Z')

Базовый принцип работы

parseISO возвращает обычный объект Date.

import { parseISO } from 'date-fns'

const date = parseISO('2025-03-15')

console.log(date instanceof Date)

Результат:

true

После разбора можно использовать любые функции JavaScript или date-fns.

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

const date = parseISO('2025-03-15')

console.log(format(date, 'dd.MM.yyyy'))

Разбор локального времени

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

parseISO('2025-03-15T10:00:00')

Если система работает в UTC+6, время останется локальным:

2025-03-15 10:00:00

Разбор UTC-времени

При наличии Z дата трактуется как UTC.

parseISO('2025-03-15T10:00:00Z')

В локальной временной зоне значение будет преобразовано автоматически.

Например, для UTC+6:

2025-03-15 16:00:00

Работа с часовыми поясами

ISO допускает указание смещения.

parseISO('2025-03-15T10:00:00+03:00')

Внутри объект Date всегда хранит UTC-время.


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

Если строка не соответствует ISO-формату, возвращается Invalid Date.

const date = parseISO('hello')

console.log(date)

Результат:

Invalid Date

Проверка через isValid

Для проверки используется функция isValid.

import { parseISO, isValid } from 'date-fns'

const date = parseISO('invalid')

console.log(isValid(date))

Результат:

false

Строгость ISO-парсинга

parseISO намеренно отвергает неоднозначные строки.

Неподдерживаемый формат

parseISO('15/03/2025')

Результат:

Invalid Date

Неполная дата

parseISO('2025/03/15')

Результат:

Invalid Date

Текстовый формат

parseISO('March 15 2025')

Результат:

Invalid Date

Отличие parseISO от parse

Функция parse используется для произвольных форматов.

import { parse } from 'date-fns'

parse('15.03.2025', 'dd.MM.yyyy', new Date())

parseISO предназначена только для ISO 8601.

parseISO('2025-03-15')

Когда использовать parseISO

API и JSON

Большинство REST API передают даты именно в ISO-формате.

{
  "createdAt": "2025-03-15T12:00:00Z"
}

Разбор:

const createdAt = parseISO(data.createdAt)

Работа с базами данных

Многие СУБД возвращают ISO-строки:

  • PostgreSQL;
  • MongoDB;
  • MySQL;
  • Prisma;
  • Supabase.

Серверные приложения

ISO является стандартом обмена датами между сервисами.


Frontend-приложения

ISO широко используется:

  • в GraphQL;
  • в REST;
  • в Firebase;
  • в SSR-framework;
  • в Next.js.

Разбор даты из API

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

const response = {
  publishedAt: '2025-08-10T14:00:00Z'
}

const date = parseISO(response.publishedAt)

console.log(
  format(date, 'dd.MM.yyyy HH:mm')
)

Обработка ошибок парсинга

Нельзя предполагать, что дата всегда корректна.

import { parseISO, isValid } from 'date-fns'

function parseApiDate(value) {
  const date = parseISO(value)

  if (!isValid(date)) {
    throw new Error('Некорректная дата')
  }

  return date
}

Разбор массива дат

import { parseISO } from 'date-fns'

const dates = [
  '2025-01-01',
  '2025-02-01',
  '2025-03-01'
]

const parsed = dates.map(parseISO)

console.log(parsed)

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

Одна из самых частых связок:

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

const date = parseISO('2025-03-15')

const formatted = format(date, 'dd MMM yyyy')

console.log(formatted)

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

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

const start = parseISO('2025-03-01')
const end = parseISO('2025-03-15')

console.log(
  differenceInDays(end, start)
)

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

import {
  parseISO,
  compareAsc
} from 'date-fns'

const result = compareAsc(
  parseISO('2025-01-01'),
  parseISO('2025-06-01')
)

console.log(result)

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

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

const result = isAfter(
  parseISO('2025-12-01'),
  parseISO('2025-01-01')
)

console.log(result)

Разбор ISO без времени

parseISO('2025-03-15')

Время автоматически устанавливается:

00:00:00

Разбор только времени невозможен

parseISO требует дату.

Некорректно:

parseISO('10:30:00')

Разбор ISO-недели

ISO поддерживает недельный формат.

parseISO('2025-W10')

Разбор даты года

Поддерживается ordinal date.

parseISO('2025-074')

74-й день года.


Особенности временных зон

Без зоны

parseISO('2025-03-15T12:00:00')

Интерпретируется как локальное время.


С UTC

parseISO('2025-03-15T12:00:00Z')

Интерпретируется как UTC.


Со смещением

parseISO('2025-03-15T12:00:00+02:00')

Интерпретируется относительно указанной зоны.


Внутреннее хранение времени

Объект Date хранит timestamp в UTC.

const date = parseISO('2025-03-15T10:00:00+03:00')

console.log(date.getTime())

Проверка на Invalid Date

Никогда не следует проверять так:

if (date === 'Invalid Date')

Правильный способ:

isValid(date)

Типичные ошибки

Использование не-ISO строк

Ошибка:

parseISO('15.03.2025')

Правильно:

parse('15.03.2025', 'dd.MM.yyyy', new Date())

Игнорирование временной зоны

Ошибка:

parseISO('2025-03-15T10:00:00')

Без указания зоны время может интерпретироваться неверно при обмене между сервером и клиентом.

Предпочтительно:

parseISO('2025-03-15T10:00:00Z')

Отсутствие проверки валидности

Ошибка:

const date = parseISO(value)

console.log(format(date, 'dd.MM.yyyy'))

Без проверки возможен runtime error.

Правильно:

const date = parseISO(value)

if (isValid(date)) {
  console.log(format(date, 'dd.MM.yyyy'))
}

Практический пример: сортировка статей

import {
  parseISO,
  compareDesc
} from 'date-fns'

const posts = [
  {
    title: 'Post 1',
    publishedAt: '2025-01-10T10:00:00Z'
  },
  {
    title: 'Post 2',
    publishedAt: '2025-02-15T09:00:00Z'
  }
]

posts.sort((a, b) =>
  compareDesc(
    parseISO(a.publishedAt),
    parseISO(b.publishedAt)
  )
)

console.log(posts)

Практический пример: проверка срока действия

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

const expiresAt = parseISO(
  '2025-12-31T23:59:59Z'
)

const expired = isAfter(
  new Date(),
  expiresAt
)

console.log(expired)

Практический пример: фильтрация событий

import {
  parseISO,
  isFuture
} from 'date-fns'

const events = [
  {
    name: 'Conference',
    date: '2026-01-10T12:00:00Z'
  },
  {
    name: 'Meetup',
    date: '2024-01-10T12:00:00Z'
  }
]

const futureEvents = events.filter(event =>
  isFuture(parseISO(event.date))
)

console.log(futureEvents)

Производительность

parseISO работает быстрее универсального parse, поскольку:

  • анализирует только ISO;
  • использует специализированный алгоритм;
  • не требует шаблона формата.

Ограничения parseISO

Функция не предназначена для:

  • локализованных дат;
  • текстовых месяцев;
  • нестандартных форматов;
  • пользовательского ввода вида 15.03.2025.

Для таких случаев применяется parse.


Совместное использование с TypeScript

import { parseISO } from 'date-fns'

const date: Date = parseISO(
  '2025-03-15'
)

Безопасная обёртка

import {
  parseISO,
  isValid
} from 'date-fns'

export function safeParseISO(value) {
  const date = parseISO(value)

  return isValid(date)
    ? date
    : null
}

Работа с nullable-значениями

function parseNullableDate(value) {
  if (!value) {
    return null
  }

  const date = parseISO(value)

  return isValid(date)
    ? date
    : null
}

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

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

function PostDate({ value }) {
  const date = parseISO(value)

  return (
    <time>
      {format(date, 'dd.MM.yyyy')}
    </time>
  )
}

Использование в Node.js

import { parseISO } from 'date-fns'

const timestamp =
  process.env.EXPIRES_AT

const date = parseISO(timestamp)

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

parseISO не работает с timestamp.

Неправильно:

parseISO(1710000000000)

Для timestamp:

new Date(1710000000000)

или:

fromUnixTime(1710000000)

Сравнение parseISO и Date.parse

Date.parse

Date.parse('2025-03-15')

Возвращает timestamp.


parseISO

parseISO('2025-03-15')

Возвращает объект Date.


Поведение при пустой строке

parseISO('')

Результат:

Invalid Date

Поведение при undefined

parseISO(undefined)

Результат:

Invalid Date

Поведение при null

parseISO(null)

Результат:

Invalid Date

Рекомендации по использованию

Для API

Использовать ISO с UTC:

2025-03-15T10:00:00Z

Для хранения

Предпочтительно хранить даты в UTC.


Для отображения

Преобразовывать через format.


Для валидации

Всегда использовать isValid.


Краткая схема работы

ISO string
    ↓
parseISO()
    ↓
Date object
    ↓
format / compare / filter / math