Форматирование даты в JavaScript: методы, локализация, примеры
Для кого эта статья:
- Веб-разработчики, ищущие информацию о форматировании дат в JavaScript
- Студенты, обучающиеся программированию и веб-разработке
Менеджеры продуктов в IT-компаниях, заинтересованные в улучшении пользовательского опыта через правильное отображение дат
Форматирование даты в JavaScript часто превращается в настоящий квест даже для опытных разработчиков. Представьте: вы создаёте интерфейс с отображением даты встречи, а пользователи из разных стран видят её в совершенно непонятном для них формате. Или ещё хуже — ваше приложение отправляет на сервер дату в неправильном формате, и транзакция проваливается. Работа с датами — это не просто "собери строку как хочешь", а целая наука со своими тонкостями, временными зонами и локалями. Давайте разберемся, как укротить этого "временного дракона" и заставить даты работать именно так, как вам нужно. 🕒
Хотите не просто читать о форматировании дат, а уверенно применять эти знания в реальных проектах? Пройдите курс Обучение веб-разработке от Skypro, где вы на практике освоите не только работу с датами, но и все ключевые аспекты современного JavaScript-программирования. Наши студенты уже через 3 месяца создают полноценные веб-приложения с продвинутой обработкой данных, включая сложное форматирование дат и времени.
Встроенные методы форматирования даты в JavaScript
JavaScript предоставляет несколько встроенных методов для работы с объектом Date. Прежде чем обращаться к сторонним библиотекам, стоит разобраться, какие возможности уже есть в языке. Встроенные методы достаточно мощные и часто могут решить большинство типичных задач форматирования дат.
Давайте рассмотрим основные методы и их возможности:
| Метод | Описание | Результат |
|---|---|---|
toString() | Возвращает строковое представление даты | Wed Jun 21 2023 12:30:00 GMT+0300 (Moscow Standard Time) |
toDateString() | Возвращает только дату (без времени) | Wed Jun 21 2023 |
toTimeString() | Возвращает только время (без даты) | 12:30:00 GMT+0300 (Moscow Standard Time) |
toISOString() | Возвращает дату в формате ISO | 2023-06-21T09:30:00.000Z |
toLocaleDateString() | Дата с учетом локали | 21.06.2023 (зависит от локали) |
toLocaleTimeString() | Время с учетом локали | 12:30:00 (зависит от локали) |
toLocaleString() | Дата и время с учетом локали | 21.06.2023, 12:30:00 (зависит от локали) |
Каждый из этих методов имеет свои особенности и область применения. Например, метод toISOString() идеально подходит для взаимодействия с API и сохранения дат в базе данных, так как возвращает строку в стандартизированном формате ISO 8601.
Александр Петров, Senior Frontend Developer
В одном из моих проектов клиент неожиданно сообщил, что в их международном приложении даты отображаются некорректно для пользователей из разных стран. У американцев месяц шел перед днем, у европейцев — день перед месяцем, а японские пользователи вообще ожидали увидеть год в начале.
Первым делом я проверил код и увидел классическую ошибку:
JSСкопировать код// Неправильный подход const date = new Date(); const formattedDate = `${date.getDate()}.${date.getMonth() + 1}.${date.getFullYear()}`;Решение было очевидным — заменить этот хардкод на гибкий метод
toLocaleDateString():JSСкопировать код// Правильное решение const date = new Date(); const formattedDate = date.toLocaleDateString(userLocale);После этого изменения каждый пользователь начал видеть дату в привычном для своей страны формате. Система автоматически определяла локаль и форматировала дату соответствующим образом. Клиент был впечатлен тем, как "маленькое" изменение значительно улучшило пользовательский опыт.
При работе с встроенными методами важно помнить о временных зонах. Например, метод toISOString() всегда возвращает дату в UTC, а toString() использует локальную временную зону пользователя. Это может привести к неожиданным результатам, если не учитывать данную особенность.

Преобразование объекта Date в строку с помощью методов
Когда встроенных методов недостаточно, и вам нужен специфический формат даты, приходится создавать собственные функции форматирования. В основе таких функций лежит извлечение отдельных компонентов даты и последующая их компоновка в нужную строку.
Основные методы для извлечения компонентов даты:
getFullYear()— возвращает год (4 цифры)getMonth()— возвращает месяц (0-11, где 0 — январь)getDate()— возвращает день месяца (1-31)getDay()— возвращает день недели (0-6, где 0 — воскресенье)getHours()— возвращает час (0-23)getMinutes()— возвращает минуты (0-59)getSeconds()— возвращает секунды (0-59)
Используя эти методы, вы можете составить любой формат даты. Вот пример создания собственной функции форматирования:
function formatDate(date, format) {
const day = date.getDate().toString().padStart(2, '0');
const month = (date.getMonth() + 1).toString().padStart(2, '0');
const year = date.getFullYear();
// Заменяем плейсхолдеры в формате на соответствующие значения
return format
.replace('DD', day)
.replace('MM', month)
.replace('YYYY', year);
}
// Пример использования
const today = new Date();
console.log(formatDate(today, 'DD.MM.YYYY')); // "21.06.2023"
console.log(formatDate(today, 'YYYY-MM-DD')); // "2023-06-21"
Обратите внимание на использование метода padStart() — он гарантирует, что числа меньше 10 будут отображаться с ведущим нулем, что особенно важно для стандартных форматов дат.
Для более сложных случаев можно создать расширенную функцию, которая поддерживает дополнительные плейсхолдеры:
function formatDateExtended(date, format) {
const tokens = {
'YYYY': date.getFullYear(),
'YY': date.getFullYear().toString().slice(-2),
'MM': (date.getMonth() + 1).toString().padStart(2, '0'),
'M': date.getMonth() + 1,
'DD': date.getDate().toString().padStart(2, '0'),
'D': date.getDate(),
'HH': date.getHours().toString().padStart(2, '0'),
'H': date.getHours(),
'mm': date.getMinutes().toString().padStart(2, '0'),
'm': date.getMinutes(),
'ss': date.getSeconds().toString().padStart(2, '0'),
's': date.getSeconds()
};
return format.replace(/YYYY|YY|MM|M|DD|D|HH|H|mm|m|ss|s/g, function(match) {
return tokens[match];
});
}
// Пример использования
console.log(formatDateExtended(new Date(), 'YYYY-MM-DD HH:mm:ss')); // "2023-06-21 12:30:45"
Локализация дат: форматирование для разных языков
Одно из главных преимуществ современного JavaScript — это мощная поддержка интернационализации через API Intl. Это позволяет форматировать даты в соответствии с локальными стандартами различных стран и языков без необходимости писать сложную логику самостоятельно. 🌍
Метод toLocaleDateString() принимает два параметра: локаль и объект с опциями форматирования. Именно благодаря этим параметрам мы можем тонко настраивать формат даты:
const date = new Date();
// Базовое использование с указанием локали
console.log(date.toLocaleDateString('en-US')); // "6/21/2023"
console.log(date.toLocaleDateString('de-DE')); // "21.6.2023"
console.log(date.toLocaleDateString('ja-JP')); // "2023/6/21"
// Расширенные опции форматирования
const options = {
weekday: 'long', // 'long', 'short', 'narrow'
year: 'numeric', // 'numeric', '2-digit'
month: 'long', // 'numeric', '2-digit', 'long', 'short', 'narrow'
day: 'numeric' // 'numeric', '2-digit'
};
console.log(date.toLocaleDateString('en-US', options));
// "Wednesday, June 21, 2023"
console.log(date.toLocaleDateString('ru-RU', options));
// "среда, 21 июня 2023 г."
console.log(date.toLocaleDateString('ja-JP', options));
// "2023年6月21日水曜日"
Для еще более тонкой настройки можно использовать объект Intl.DateTimeFormat, который предоставляет дополнительные возможности по форматированию дат:
const date = new Date();
const formatter = new Intl.DateTimeFormat('ru-RU', {
year: 'numeric',
month: 'long',
day: 'numeric',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
hour12: false, // Используем 24-часовой формат
timeZone: 'Europe/Moscow'
});
console.log(formatter.format(date)); // "21 июня 2023 г., 12:30:45"
API Intl позволяет также форматировать относительные даты, что может быть полезно для интерфейсов социальных сетей или новостных лент:
const rtf = new Intl.RelativeTimeFormat('ru', { style: 'long' });
// Для дат в прошлом используем отрицательные значения
console.log(rtf.format(-1, 'day')); // "1 день назад"
console.log(rtf.format(-2, 'day')); // "2 дня назад"
// Для дат в будущем используем положительные значения
console.log(rtf.format(1, 'month')); // "через 1 месяц"
console.log(rtf.format(3, 'year')); // "через 3 года"
Мария Ковалева, Product Manager в IT-компании
Когда мы запустили новую версию нашего сервиса доставки, я столкнулась с настоящим кризисом. Пользователи из разных стран получали противоречивую информацию о времени доставки — кто-то видел даты в формате MM/DD/YYYY, кто-то в DD.MM.YYYY, а некоторые вообще получали названия месяцев на английском, независимо от их родного языка.
Техническая команда быстро определила проблему: все форматирование дат было жестко закодировано под американский формат. Решение потребовало системного подхода:
JSСкопировать код// Старый код function formatDeliveryDate(date) { return `${date.getMonth() + 1}/${date.getDate()}/${date.getFullYear()}`; } // Новый код с использованием локализации function formatDeliveryDate(date, locale = navigator.language) { const options = { year: 'numeric', month: 'long', day: 'numeric', weekday: 'long' }; return date.toLocaleDateString(locale, options); }После внедрения этих изменений количество жалоб на непонятные даты доставки упало до нуля. А когда мы добавили точное время с учётом часовых поясов с помощью toLocaleTimeString(), показатель удовлетворённости пользователей вырос на 18%. Это был отличный урок того, как небольшие технические улучшения могут существенно повлиять на бизнес-метрики.
Практические примеры кода для часто используемых форматов
В ежедневной работе разработчики часто сталкиваются с необходимостью использовать определенные форматы дат. Ниже приведены готовые решения для наиболее распространенных случаев — просто скопируйте код и адаптируйте под свои нужды. 💼
| Формат | Пример | Код | Применение |
|---|---|---|---|
| ISO 8601 | 2023-06-21T12:30:45.000Z | date.toISOString() | API, хранение в БД |
| Короткая дата | 21.06.2023 | date.toLocaleDateString('ru-RU') | Интерфейсы, списки |
| Дата и время | 21.06.2023, 12:30 | date.toLocaleString('ru-RU') | Логи, временные метки |
| Относительное время | 2 часа назад | new Intl.RelativeTimeFormat().format(-2, 'hour') | Социальные сети, чаты |
| Год и месяц | Июнь 2023 | date.toLocaleDateString('ru-RU', { year: 'numeric', month: 'long' }) | Календари, графики |
Давайте рассмотрим несколько конкретных примеров, которые могут пригодиться при разработке веб-приложений:
- Форматирование даты для ввода в HTML-форме (
input type="date"):
function formatDateForInput(date) {
return date.toISOString().split('T')[0]; // Возвращает "YYYY-MM-DD"
}
// Пример использования
const dateInput = document.querySelector('input[type="date"]');
dateInput.value = formatDateForInput(new Date());
- Создание читаемого диапазона дат для бронирования или мероприятий:
function formatDateRange(startDate, endDate, locale = 'ru-RU') {
const options = { day: 'numeric', month: 'long', year: 'numeric' };
const sameYear = startDate.getFullYear() === endDate.getFullYear();
const sameMonth = sameYear && startDate.getMonth() === endDate.getMonth();
if (sameMonth) {
// Формат: "1-5 января 2023"
return `${startDate.getDate()}-${endDate.getDate()} ${endDate.toLocaleDateString(locale, { month: 'long', year: 'numeric' })}`;
} else if (sameYear) {
// Формат: "25 декабря – 10 января 2023"
return `${startDate.getDate()} ${startDate.toLocaleDateString(locale, { month: 'long' })} – ${endDate.getDate()} ${endDate.toLocaleDateString(locale, { month: 'long', year: 'numeric' })}`;
} else {
// Формат: "25 декабря 2022 – 10 января 2023"
return `${startDate.toLocaleDateString(locale, options)} – ${endDate.toLocaleDateString(locale, options)}`;
}
}
// Пример использования
const start = new Date(2023, 5, 21); // 21 июня 2023
const end = new Date(2023, 5, 28); // 28 июня 2023
console.log(formatDateRange(start, end)); // "21-28 июня 2023"
- Добавление временных меток к сообщениям в чате:
function formatMessageTime(date) {
const now = new Date();
const isToday = now.toDateString() === date.toDateString();
const isThisYear = now.getFullYear() === date.getFullYear();
if (isToday) {
// Если сообщение сегодня, показываем только время
return date.toLocaleTimeString('ru-RU', { hour: '2-digit', minute: '2-digit' });
} else if (isThisYear) {
// Если сообщение в этом году, показываем день и месяц
return date.toLocaleDateString('ru-RU', { day: 'numeric', month: 'short' });
} else {
// Иначе показываем полную дату
return date.toLocaleDateString('ru-RU', { day: 'numeric', month: 'short', year: 'numeric' });
}
}
// Примеры использования
const now = new Date();
const yesterday = new Date(now);
yesterday.setDate(yesterday.getDate() – 1);
const lastYear = new Date(now);
lastYear.setFullYear(lastYear.getFullYear() – 1);
console.log(formatMessageTime(now)); // "12:30"
console.log(formatMessageTime(yesterday)); // "20 июн"
console.log(formatMessageTime(lastYear)); // "21 июн 2022"
- Форматирование даты для URL или идентификаторов:
function formatDateForUrl(date) {
return date.toISOString().replace(/[:.]/g, '-').replace('T', '_').slice(0, -5);
}
// Пример использования
const filename = `report_${formatDateForUrl(new Date())}.pdf`;
console.log(filename); // "report_2023-06-21_12-30-45.pdf"
Библиотеки для эффективной работы с датами в JavaScript
Несмотря на то, что встроенные методы JavaScript для работы с датами достаточно мощные, в сложных проектах часто требуются более продвинутые возможности, которые предоставляют специализированные библиотеки. Они значительно упрощают манипуляции с датами, расчёт разницы между датами, добавление/вычитание временных интервалов и форматирование. 📚
Рассмотрим наиболее популярные библиотеки:
- date-fns — модульная библиотека с функциональным подходом
- Luxon — современная альтернатива Moment.js с улучшенной поддержкой временных зон
- Day.js — минималистичная библиотека, совместимая с Moment.js API
- js-Joda — порт Java-библиотеки JSR-310, с неизменяемыми объектами и расширенными возможностями
Давайте сравним эти библиотеки по ключевым параметрам:
| Библиотека | Размер (min+gzip) | Неизменяемые объекты | Цепочки методов | Временные зоны | Tree-shaking |
|---|---|---|---|---|---|
| date-fns | ~2 KB (базовый импорт) | Да (с v2.0) | Нет | Через отдельный пакет | Да |
| Luxon | ~13 KB | Да | Да | Встроенная поддержка | Нет |
| Day.js | ~2 KB | Да | Да | Через плагины | Частично |
| js-Joda | ~45 KB | Да | Да | Через отдельный пакет | Нет |
Примеры использования библиотек:
date-fns — функциональный подход к манипуляции датами:
import { format, addDays, differenceInDays } from 'date-fns';
import { ru } from 'date-fns/locale';
const today = new Date();
const futureDate = addDays(today, 10);
// Форматирование
console.log(format(today, 'dd MMMM yyyy', { locale: ru }));
// "21 июня 2023"
// Разница между датами
const daysDiff = differenceInDays(futureDate, today);
console.log(`До события осталось дней: ${daysDiff}`);
// "До события осталось дней: 10"
Luxon — работа с временными зонами и форматирование:
import { DateTime } from 'luxon';
// Создание даты в определенной временной зоне
const dt = DateTime.fromISO('2023-06-21T12:30:00', {
zone: 'Europe/Moscow'
});
// Форматирование
console.log(dt.setLocale('ru').toFormat('dd MMMM yyyy, HH:mm'));
// "21 июня 2023, 12:30"
// Преобразование во временную зону Нью-Йорка
const nyTime = dt.setZone('America/New_York');
console.log(nyTime.toFormat('dd MMMM yyyy, HH:mm'));
// "21 июня 2023, 05:30" (зависит от летнего времени)
Day.js — легковесная альтернатива с плагинами:
import dayjs from 'dayjs';
import 'dayjs/locale/ru';
import relativeTime from 'dayjs/plugin/relativeTime';
import customParseFormat from 'dayjs/plugin/customParseFormat';
// Подключаем плагины
dayjs.extend(relativeTime);
dayjs.extend(customParseFormat);
dayjs.locale('ru');
// Создаем дату
const date = dayjs('2023-06-21');
// Форматирование
console.log(date.format('DD MMMM YYYY'));
// "21 июня 2023"
// Относительное время
console.log(date.fromNow());
// "через X дней" или "X дней назад" в зависимости от текущей даты
При выборе библиотеки стоит учитывать несколько факторов:
- Размер бандла — для мобильных приложений или небольших проектов лучше выбирать легковесные решения вроде Day.js
- Возможность tree-shaking — date-fns позволяет импортировать только нужные функции
- Неизменяемость объектов — критично для предотвращения неожиданных мутаций дат
- Поддержка временных зон — важно для международных приложений
- Удобство API — Luxon и Day.js предлагают цепочки методов, что улучшает читаемость кода
Существует также специализированные библиотеки для конкретных задач, например:
- date-holidays — для работы с праздниками в разных странах
- spacetime — библиотека с акцентом на понятный API для работы с временными зонами
- calendar-base — для создания календарей и вычисления календарных дат
Работа с датами в JavaScript прошла долгий путь от примитивных манипуляций строками до мощных API с поддержкой интернационализации и временных зон. Независимо от того, используете ли вы встроенные методы или специализированные библиотеки, важно понимать основные принципы форматирования дат и выбирать подход, соответствующий требованиям вашего проекта. Правильная обработка дат не только улучшает пользовательский опыт, но и предотвращает множество скрытых ошибок, которые могут возникнуть при неверном понимании временных данных.