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. Сейчас использовать её не рекомендуется, так как она сильно увеличивает размер собранного приложения. Не добавляйте её в новые проекты.