Date

Объект для манипуляции с датой и временем.

Время чтения: 8 мин

Кратко

Скопировано

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

Время отображается в двух форматах:

  1. UTC — время по Гринвичу.
  2. В текущей часовой зоне (например, UTC+3 для Москвы).

Поэтому часть методов для взаимодействия со временем имеют два формата — для UTC и для текущей часовой зоны.

Как понять

Скопировано

Класс Date используется для отображения даты в различных форматах. Там, где нужно находить разницу между датами, Date тоже прекрасно справится.

Пример

Скопировано

Создадим новый экземпляр даты:

        
          
          const currentDate = new Date('August 14, 2022 14:15:30')
          const currentDate = new Date('August 14, 2022 14:15:30')

        
        
          
        
      

Получаем различные части даты:

        
          
          console.log(currentDate.getDay())// 0console.log(currentDate.getHours())// 14console.log(currentDate.getTime())// 1660475730000console.log(currentDate.getFullYear())// 2022console.log(currentDate.toISOString())// 2022-08-14T11:15:30.000Z
          console.log(currentDate.getDay())
// 0

console.log(currentDate.getHours())
// 14

console.log(currentDate.getTime())
// 1660475730000

console.log(currentDate.getFullYear())
// 2022

console.log(currentDate.toISOString())
// 2022-08-14T11:15:30.000Z

        
        
          
        
      

Установим новую дату:

        
          
          currentDate.setMonth(0, 1)console.log(currentDate.toLocaleDateString())// 01.01.2022
          currentDate.setMonth(0, 1)

console.log(currentDate.toLocaleDateString())
// 01.01.2022

        
        
          
        
      

Также можно создавать дату в формате UTC:

        
          
          const utcDate = new Date(Date.UTC(2022, 8, 14, 14, 15, 30))console.log(utcDate.toISOString())// 2022-09-14T14:15:30.000Z
          const utcDate = new Date(Date.UTC(2022, 8, 14, 14, 15, 30))

console.log(utcDate.toISOString())
// 2022-09-14T14:15:30.000Z

        
        
          
        
      

Как пишется

Скопировано

Date может немного запутать, часть параметров начинают отсчёт с нуля, а часть с 1.

Например, при установке месяца, отсчёт идёт с 0, где 0 — это январь. При выводе дня недели возвращаемое значение также начинается с 0 и означает воскресенье.

Исключением из этого правила являются параметры, связанные с годом и днём месяца (первое число месяца — 1).

Основные методы

Скопировано

Создание

Скопировано

Создать новый экземпляр класса можно несколькими способами:

new Date() создаёт экземпляр Date с текущей датой и временем.

new Date(значение) создаёт Date с переданным значением времени. Значение должно быть в формате, который распознается методом Date.parse(), то есть быть совместимым с IETF RFC 2822 или с ISO8601.

new Date(год, месяц, день, часы, минуты, секунды, миллисекунды) создаёт класс Date в местной часовой зоне. Год и месяц являются обязательными параметрами. Остальные параметры, начиная с часов, будут по умолчанию равны 0, а день — 1.

new Date(миллисекунды) создаёт Date со временем в миллисекундах. Количество миллисекунд измеряется с 1 января 1970 года UTC.

        
          
          const millisecondsDate = new Date(120000)console.log(millisecondsDate.toISOString())// 1970-01-01T00:02:00.000Z
          const millisecondsDate = new Date(120000)

console.log(millisecondsDate.toISOString())
// 1970-01-01T00:02:00.000Z

        
        
          
        
      

Получение значений

Скопировано
  • getFullYear() — возвращает год;
  • getMonth() — возвращает месяц с 0 до 11;
  • getDate() — возвращает день месяца с 1 до 31;
  • getDay() — возвращает порядковый номер дня недели с 0 до 6;
  • getHours() — возвращает часы с 0 до 23;
  • getMinutes() — возвращает минуты от 0 до 59;
  • getSeconds() — возвращает секунды от 0 до 59;
  • getMilliseconds() — возвращает миллисекунды от 0 до 999.

Все вышеперечисленные методы возвращают значения для текущей часовой зоны. Если необходимо вернуть время по Гринвичу, то нужно в метод добавить UTC: getUTCFullYear(), getUTCMonth(), getUTCDate(), getUTCDay(), getUTCHours(), getUTCMinutes(), getUTCSeconds(), getUTCMilliseconds().

Есть два метода, которые не привязаны к часовой зоне:

getTime() возвращает значение в миллисекундах, прошедших с 1 января 1970 года, соответствующее указанной дате по UTC.

        
          
          const currentDate = new Date(2022, 11)console.log(currentDate.toISOString())// 2022-11-30T21:00:00.000Zconsole.log(currentDate.getTime())// 1672520400000
          const currentDate = new Date(2022, 11)

console.log(currentDate.toISOString())
// 2022-11-30T21:00:00.000Z

console.log(currentDate.getTime())
// 1672520400000

        
        
          
        
      

getTimezoneOffset() возвращает смещение в минутах между текущей часовой зоной и UTC.

        
          
          const currentDate = new Date()console.log(currentDate.getTimezoneOffset())// -180
          const currentDate = new Date()

console.log(currentDate.getTimezoneOffset())
// -180

        
        
          
        
      

Установка значений

Скопировано

Также, как и с получением значений, у многих методов есть присваивание значений в локальной часовой зоне и UTC. Для локальной:

  • setFullYear(год, месяц, день) — устанавливает год, значения месяца и дня необязательны.
  • setMonth(месяц, день) — устанавливает месяц, передавать день необязательно.
  • setDate(день) — устанавливает день месяца.
  • setHours(часы, минуты, секунды, миллисекунды) — устанавливает часы. Значения минут, секунд, миллисекунд необязательны.
  • setMinutes(минуты, секунды, миллисекунды) — устанавливает минуты. Секунды и миллисекунды необязательны.
  • setSeconds(секунды, миллисекунды) — устанавливает секунды. Миллисекунды передавать необязательно.
  • setMilliseconds(миллисекунды) — устанавливает миллисекунды.

Для UTC аналогичные методы, только добавляем UTC после set. Например, setUTCMilliseconds(миллисекунды).

И метод, который относится только к UTC, — setTime(значение) устанавливает значение, которое равно количеству миллисекунд, прошедших с 1 января 1970 года.

Разбор даты

Скопировано

Метод Date.parse(значение) используется для разбора (ещё говорят парсинга) строкового представления даты. Возвращает значение, равное количеству миллисекунд, прошедших с 1 января 1970 года.

Переданное значение должно быть совместимым с IETF RFC 2822 или с ISO8601.

        
          
          console.log(Date.parse('2022-11-30T21:00:00.000Z'))// 1669842000000
          console.log(Date.parse('2022-11-30T21:00:00.000Z'))
// 1669842000000

        
        
          
        
      

Форматирование даты

Скопировано

Для отображения Date в различных форматах существует метод toLocaleDateString(локаль, опции).

Локаль — это необязательный параметр, который является строкой или массивом строк с языковой меткой BCP 47. Например, en-US или de-DE. Локаль хранит региональные настройки о формате дат, номеров, адресов.

Опции — необязательный параметр с объектом настроек. Доступные свойства:

  • localeMatcher — алгоритм поиска локали, используется для выбора подходящей локали. Принимает значения lookup или best fit. По умолчанию best fit.
  • timeZone — значение используемого часовой зоны. Все браузеры должны принимать значение UTC, значение по умолчанию равно значению часовой зоны среды выполнения. Формат принимаемого значения может различаться в различных браузерах.
  • hour12 — значение, которое определяет, использовать ли 12-часовой формат вывода. Принимает true или false.
  • formatMatcher — алгоритм поиска формата, используется для выбора формата отображения. Принимает значения basic или best fit. По умолчанию best fit.
  • timeZoneName — формат названия часовой зоны. Принимает long или short.
  • weekday — значение дня недели. Принимает narrow, short и long.
  • era — значение эры. Принимает narrow, short и long.
  • year — значение года. Принимает numeric и 2-digit.
  • month — значения месяца. Принимает numeric, 2-digit, narrow, short и long.
  • day — значения дня. Принимает numeric и 2-digit.
  • hour — значения часа. Принимает numeric и 2-digit.
  • minute — значения минут. Принимает numeric и 2-digit.
  • second — значения секунд. Принимает numeric и 2-digit.

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

  • weekday, year, month, day, hour, minute, second;
  • weekday, year, month, day;
  • year, month, day;
  • year, month;
  • month, day;
  • hour, minute, second;
  • hour, minute.

Некоторые браузеры могут поддерживать форматы вывода сверх этих наборов, но данный момент необходимо уточнять в спецификации браузеров.

Отобразим в двух форматах:

        
          
          const currentDate = new Date('August 14, 2022 14:15:30')const options = {  hour: 'numeric', minute: 'numeric', second: 'numeric',  timeZoneName: 'long'}console.log(currentDate.toLocaleDateString('ru-RU', options))// 14.08.2022, 14:15:30 Москва, стандартное времяconsole.log(currentDate.toLocaleDateString('en-US', options))// 8/14/2022, 2:15:30 PM Moscow Standard Time
          const currentDate = new Date('August 14, 2022 14:15:30')

const options = {
  hour: 'numeric', minute: 'numeric', second: 'numeric',
  timeZoneName: 'long'
}

console.log(currentDate.toLocaleDateString('ru-RU', options))
// 14.08.2022, 14:15:30 Москва, стандартное время

console.log(currentDate.toLocaleDateString('en-US', options))
// 8/14/2022, 2:15:30 PM Moscow Standard Time

        
        
          
        
      

Получение текущего времени

Скопировано

Date.now() — метод, который возвращает текущее время в миллисекундах, прошедших с 1 января 1970 года UTC.

Метод очень похож на new Date(), но, так как нет ключевого слова new, экземпляр класса не создаётся, возвращается только число:

        
          
          console.log(Date.now())// 1661370397669
          console.log(Date.now())
// 1661370397669

        
        
          
        
      

Математические операции

Скопировано

Найдём количество дней между 1 января 2022 и 31 декабря 2022.

Полученное значение равно количеству дней в году минус 1.

        
          
          const utcDateOne = new Date(Date.UTC(2022, 0, 1, 0, 0, 0))const utcDateTwo = new Date(Date.UTC(2022, 11, 31, 0, 0, 0))console.log(utcDateOne.toUTCString())// Sat, 01 Jan 2022 00:00:00 GMTconsole.log(utcDateTwo.toUTCString())// Sat, 31 Dec 2022 00:00:00 GMTconst result = utcDateTwo - utcDateOneconsole.log(result)// 31449600000 миллисекундconsole.log(result / (1000 * 60 * 60 * 24))// 364
          const utcDateOne = new Date(Date.UTC(2022, 0, 1, 0, 0, 0))
const utcDateTwo = new Date(Date.UTC(2022, 11, 31, 0, 0, 0))

console.log(utcDateOne.toUTCString())
// Sat, 01 Jan 2022 00:00:00 GMT

console.log(utcDateTwo.toUTCString())
// Sat, 31 Dec 2022 00:00:00 GMT

const result = utcDateTwo - utcDateOne
console.log(result)
// 31449600000 миллисекунд

console.log(result / (1000 * 60 * 60 * 24))
// 364

        
        
          
        
      

Автокоррекция даты

Скопировано

Date имеет интересное свойство: этот класс автоматически исправляет некорректно введённые значения. Например, при попытке установки 32 декабря, Date прибавит 1 день к максимальному корректному значению (31 декабря) и установит корректную дату.

        
          
          const newDate = new Date()newDate.setFullYear(2022, 11, 32)console.log(newDate.toISOString())// 2023-01-01T14:41:49.635Z
          const newDate = new Date()

newDate.setFullYear(2022, 11, 32)

console.log(newDate.toISOString())
// 2023-01-01T14:41:49.635Z

        
        
          
        
      

С минусом тоже сработает. Только Date будет вычитать значение:

        
          
          const newDate = new Date()newDate.setFullYear(1996, -11, 24)console.log(newDate.toISOString())// 1995-02-24T05:17:21.204Z
          const newDate = new Date()

newDate.setFullYear(1996, -11, 24)

console.log(newDate.toISOString())
// 1995-02-24T05:17:21.204Z

        
        
          
        
      

Также можно установить нулевое значение там, где Date возвращает ненулевые значения. Например, для дня месяца. Тогда класс просто вычтет 1 день.

        
          
          const newDate = new Date('August 14, 2022 14:15:30')newDate.setDate(0)console.log(newDate.toISOString())// 2022-07-31T11:15:30.000Z
          const newDate = new Date('August 14, 2022 14:15:30')

newDate.setDate(0)

console.log(newDate.toISOString())
// 2022-07-31T11:15:30.000Z

        
        
          
        
      
        
          
          // Обе переменных представляют одну и ту же датуconst dateOne = new Date(Date.UTC(2022, 11, 31, 0, 0, 0))const dateTwo = new Date(Date.UTC(2022, 12, 0, 0, 0, 0))console.log(dateOne.toISOString())console.log(dateTwo.toISOString())// 2022-12-31T00:00:00.000Z// 2022-12-31T00:00:00.000Z
          // Обе переменных представляют одну и ту же дату
const dateOne = new Date(Date.UTC(2022, 11, 31, 0, 0, 0))
const dateTwo = new Date(Date.UTC(2022, 12, 0, 0, 0, 0))

console.log(dateOne.toISOString())
console.log(dateTwo.toISOString())
// 2022-12-31T00:00:00.000Z
// 2022-12-31T00:00:00.000Z

        
        
          
        
      

Альтернативы

Скопировано

Вместо использования toLocaleDateString() можно использовать класс Intl.DateTimeFormat.

        
          
          const currentDate = new Date('August 14, 2022 14:15:30')const options = {  year: 'numeric', month: 'numeric', day: 'numeric',  hour: 'numeric', minute: 'numeric', second: 'numeric',  timeZoneName: 'long'}console.log(new Intl.DateTimeFormat('ru-RU', options).format(currentDate))// 14.08.2022, 14:15:30 Москва, стандартное времяconsole.log(new Intl.DateTimeFormat('en-US', options).format(currentDate))// 8/14/2022, 2:15:30 PM Moscow Standard Time
          const currentDate = new Date('August 14, 2022 14:15:30')

const options = {
  year: 'numeric', month: 'numeric', day: 'numeric',
  hour: 'numeric', minute: 'numeric', second: 'numeric',
  timeZoneName: 'long'
}

console.log(new Intl.DateTimeFormat('ru-RU', options).format(currentDate))
// 14.08.2022, 14:15:30 Москва, стандартное время

console.log(new Intl.DateTimeFormat('en-US', options).format(currentDate))
// 8/14/2022, 2:15:30 PM Moscow Standard Time

        
        
          
        
      

На практике

Скопировано

Ксения Субботина советует

Скопировано

🛠 Intl.DateTimeFormat и toLocaleDateString() реализовывают похожую функциональность, но есть небольшая разница в использовании.

Их реализация в браузерах также может отличаться, так как нет строгой спецификации и каждый браузер может интерпретировать требования по-разному. Поэтому нет универсального решения, что именно использовать.

Основные отличия.

В поддержке браузеров. Intl.DateTimeFormat поддерживается не всеми древними браузерами.

Вы можете использовать Intl.DateTimeFormat для форматирования групп дат. В отличие от toLocaleDateString(), он позволяет установить формат один раз.

        
          
          const dateOne = new Date('August 14, 2022 14:15:30')const dateTwo = new Date('December 26, 1991 02:00:30')const options = {  year: 'numeric', month: 'numeric', day: 'numeric',  hour: 'numeric', minute: 'numeric', second: 'numeric',  timeZoneName: 'long',  timeZone: 'UTC'}const formatter = new Intl.DateTimeFormat('ru-RU', options)console.log(formatter.format(dateOne))// 14.08.2022, 11:15:30 Всемирное координированное времяconsole.log(formatter.format(dateTwo))// 26.12.1991, 0:00:30 Всемирное координированное время
          const dateOne = new Date('August 14, 2022 14:15:30')
const dateTwo = new Date('December 26, 1991 02:00:30')

const options = {
  year: 'numeric', month: 'numeric', day: 'numeric',
  hour: 'numeric', minute: 'numeric', second: 'numeric',
  timeZoneName: 'long',
  timeZone: 'UTC'
}

const formatter = new Intl.DateTimeFormat('ru-RU', options)

console.log(formatter.format(dateOne))
// 14.08.2022, 11:15:30 Всемирное координированное время

console.log(formatter.format(dateTwo))
// 26.12.1991, 0:00:30 Всемирное координированное время

        
        
          
        
      

Различный ввод или вывод. Так как стандарт не является строгим, то передаваемые параметры могут отличаться. Особенно это касается часовых зон. Значения вывода по умолчанию также могут отличаться.

        
          
          const date = new Date(1660475730000)console.log(date.toLocaleString('en-US'))// 8/14/2022, 2:15:30 PMconsole.log(new Intl.DateTimeFormat('en-US').format(date))// 8/14/2022
          const date = new Date(1660475730000)

console.log(date.toLocaleString('en-US'))
// 8/14/2022, 2:15:30 PM

console.log(new Intl.DateTimeFormat('en-US').format(date))
// 8/14/2022

        
        
          
        
      

Поэтому, если вам не так критично поддерживать браузеры, с маленьким процентом использования клиентами, то советую использовать Intl.DateTimeFormat.

🛠 Если вам не хватает функциональности, представленной классом Date, например, недостаточно его возможностей форматирования или парсинга, то можно посмотреть в сторону библиотек day.js или date-fns.

🛠 Раньше золотым стандартом была библиотека moment.js. Сейчас использовать её не рекомендуется, так как она сильно увеличивает размер собранного приложения. Не добавляйте её в новые проекты.