Дата и время JS: все, что нужно знать

Изучаем дату и время JS. В этой статье я расскажу все, что вам нужно знать об объекте Date, входящем в состав JavaScript.

Часовые пояса

В JavaScript для операций с датами используется только два часовых пояса: местное время и всемирное координированное время (UTC).

  • Местное время относится к часовому поясу вашего компьютера.
  • UTC на практике является синонимом времени по Гринвичу (GMT).

По умолчанию почти каждый метод объекта Date возвращает дату и время по местному часовому поясу. Вы получите UTC, только если явно укажете это.

Создание даты

Вы можете создать дату, использовав оператор new:

  1. Со строкой даты.
  2. С аргументами даты.
  3. С меткой времени.
  4. Без аргументов.

Способ со строкой даты

Мы передаем строку даты в конструктор new Date.

new Date('1988-03-21')

Но если вы передадите строковое представление даты в формате 21-03-1988, то получите ошибку.

Способ со строкой даты

new Date('21-03-1988') приводит к ошибке Invalid Date.

В JavaScript нужно использовать формат даты, который принят во всем мире -  ISO 8601.

// Расширенный формат ISO 8601
`YYYY-MM-DDTHH:mm:ss:sssZ`

Вот что означают значения:

  • YYYY: 4-значный год;
  • MM: двузначный месяц (где январь 01, а декабрь 12);
  • DD: двузначная дата (от 01 до 31);
  • -: разделители даты;
  • T: указывает на начало блока времени;
  • HH: часы в 24-часовом формате (от 00 до 23);
  • mm: минуты (от 00 до 59);
  • ss: секунды (от 00 до 59);
  • sss: миллисекунды (от 000 до 999);
  • :: разделители времени;
  • Z: если Z присутствует, дата будет установлена в UTC. Если Z отсутствует, это будет местное время.

Часы, минуты, секунды и миллисекунды необязательны, если вы создаете дату. Если нужно передать дату 11 июня 2019 года:

new Date('2019-06-11')

Но если вы находитесь к востоку от Гринвича, то получите дату 10 июня.

Способ со строкой даты - 2

new Date('2019-06-11') выдаёт 10 июня, если вы находитесь к востоку от Гринвича

Если в районе, который опережает время по Гринвичу, то получите дату 11 июня.

new Date('2019-06-11') выдаёт 11 июня, если вы находитесь к западу от Гринвича

Это происходит потому, что вы передаете дату без указания времени. В итоге JavaScript выводит дату, установленную в UTC.

Строка кода new Date('2019-06-11') создает дату 11 июня 2019, 12:00 UTC. Вот почему люди, которые живут восточнее Гринвича, получают 10 июня вместо 11 июня.

Если вы хотите создать дату по местному часовому поясу, необходимо указать время. Когда вы включаете в дату время, вам нужно добавить, как минимум, часы и минуты (иначе Google Chrome возвращает недопустимую дату).

new Date('2019-06-11T00:00')

Дата по местному времени и дата в UTC.

Кстати, MDN предостерегает от использования строкового представления даты, поскольку браузеры могут ее трактовать по-разному.

MDN не рекомендует создавать даты с помощью строкового представления.

Создание дат с помощью аргументов

Конструктор Date принимает семь параметров:

  1. Год: четырехзначный год.
  2. Месяц: месяц года (0-11). По умолчанию 0.
  3. День: день месяца (1-31). По умолчанию 1.
  4. Час: час дня (0-23). По умолчанию 0.
  5. Минуты: Минуты (0-59). По умолчанию 0.
  6. Секунды: секунды (0-59). По умолчанию 0.
  7. Миллисекунды: миллисекунды (0-999). По умолчанию 0.
// 11 июня 2019г. 5:23:59 местного времени
new Date(2019, 5, 11, 5, 23, 59)

Многие разработчики избегают подхода с использованием аргументов, потому что он выглядит сложным. Но на самом деле все довольно просто.

new Date(2017, 3, 22, 5, 23, 50)
// Эту дату легко понять, если читать ее слева направо.
// Год: 2017
// Месяц: апрель (потому что месяца считаются с 0)
// Дата: 22
// Часы: 05
// Минут: 23
// Секунды: 50

Но помните, что порядок месяца начинаются с нуля. Например, январь – 0, февраль – 1, март – 2 и т. д.

Вот еще несколько примеров для закрепления:

// 21 марта 1988г. 00:00 местного времени
new Date(1988, 2, 21)
// 25 декабря 2019г. 8:00 местного времени 
new Date(2019, 11, 25, 8)
// 6 ноября 2023г. 2:20 местного времени
new Date(2023, 10, 6, 2, 20)
// 11 июня 2019г. 5:23:59 местного времени
new Date(2019, 5, 11, 5, 23, 59)

Даты, созданные с помощью аргументов, указаны по местному времени. Если вам понадобится дата в формате UTC, используйте следующий синтаксис:

// 11 июня 2019 00:00 UTC.
new Date(Date.UTC(2019, 5, 11))

Создание дат с помощью меток времени

В JavaScript метка времени – это количество миллисекунд, прошедших с 1 января 1970 г. (от начала эпохи Unix). Метки времени используются только для сравнения различных дат.

// 11 июня 2019 8:00 (по моему местному времени в Сингапуре)
new Date(1560211200000)

Без аргументов

Если использовать конструктор объекта Date() без аргументов, то он возвращает дату по местному времени.

new Date()

Без аргументов

Текущее время.

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

Объект Date предоставляет семь методов форматирования. Каждый из этих семи методов возвращает определенное значение (и все они совершенно бесполезны).

const date = new Date(2019, 0, 23, 17, 23, 42)
  1. toString выдаст Wed Jan 23 2019 17:23:42 GMT+0800 (Singapore Standard Time)
  2. toDateString выдаст Wed Jan 23 2019
  3. toLocaleString выдаст 23/01/2019, 17:23:42
  4. toLocaleDateString выдаст 23/01/2019
  5. toGMTString выдаст Wed, 23 Jan 2019 09:23:42 GMT
  6. toUTCString выдаст Wed, 23 Jan 2019 09:23:42 GMT
  7. toISOString выдаст 2019-01-23T09:23:42.079Z

Если вам нужен собственный формат, то придётся создать его самостоятельно.

Создаем собственный формат даты JS

Чтобы получить дату в формате Четверг, 23 января 2019, нужно применять методы объекта Date:

  1. getFullYear: возвращает четырехзначный год по местному времени.
  2. getMonth: возвращает месяц года (0-11) по местному времени.
  3. getDate: возвращает день месяца (1-31) по местному времени.
  4. getDay: возвращает день недели (0-6) по местному времени. Неделя начинается с воскресенья (0) и заканчивается субботой (6).

Чтобы получить Четверг, 23 января 2019, нужно использовать методы getFullYear и getDate:

const d = new Date(2019, 0, 23)
const year = d.getFullYear() // 2019
const date = d.getDate() // 23

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

const months = {
  0: 'января',
  1: 'февраля',
  2: 'марта',
  3: 'апреля',
  4: 'мая',
  5: 'июня',
  6: 'июля',
  7: 'августа',
  8: 'сентября',
  9: 'октября',
  10: 'ноября',
  11: 'декабря'
}

Поскольку год начинается с нулевого месяца, то можно использовать массив вместо объекта.

const months = [
  'января',
  'февраля',
  'марта',
  'апреля',
  'мая',
  'июня',
  'июля',
  'августа',
  'сентября',
  'октября',
  'ноября',
  'декабря'
]

Чтобы получить названием месяца:

  1. Нужно использовать getMonth, чтобы получить индекс месяца.
  2. Получить название месяца из months.
const monthIndex = d.getMonth()
const monthName = months[monthIndex]
console.log(monthName) // января

Краткая версия:

const monthName = months(d.getMonth())
console.log(monthName) // января

Чтобы вывести день недели, нужен массив со всеми названиями:

const days = [
  'Воскресенье',
  'Понедельник',
  'Вторник',
  'Среда',
  'Четверг',
  'Пятница',
  'Суббота'
]

Затем:

  1. Получаем dayIndex с помощью getDay.
  2. Используем dayIndex, чтобы получить dayName.
const dayIndex = d.getDay()
const dayName = days[dayIndex] // Четверг

Краткая версия:

const dayName = days[d.getDay()] // Четверг

Объединим все переменные, которые создали, чтобы получить отформатированную строку.

const formatted = '${dayName}, ${date} ${monthName} ${year}'
console.log(formatted) // Четверг, 23 января 2019

Для форматирования времени используйте следующие методы:

  1. getHours: выдаст часы (0-23) по местному времени.
  2. getMinutes: выдаст минуты (0-59) по местному времени.
  3. getSeconds: выдаст секунды (0-59) по местному времени.
  4. getMilliseconds: выдаст миллисекунды (0-999) по местному времени.

JS сравнение дат

В JavaScript для сравнения дат используются операторы >, <, >= и <=.

const earlier = new Date(2019, 0, 26)
const later = new Date(2019, 0, 27)
console.log(earlier < later) // true

Сложнее сравнить даты по времени суток (часам и минутам). Вы не сможете сравнить их с помощью == или ===:

const a = new Date(2019, 0, 26)
const b = new Date(2019, 0, 26)

console.log(a == b) // false
console.log(a === b) // false

Чтобы проверить, совпадает ли в двух датах значение времени, нужно сравнить их временные метки с помощью getTime.

const isSameTime = (a, b) => {
  return a.getTime() === b.getTime()
}
const a = new Date(2019, 0, 26)
const b = new Date(2019, 0, 26)
console.log(isSameTime(a, b)) // true

Чтобы проверить, совпадают ли в датах дни недели, сравните их значения  с помощью методов getFullYear, getMonth и getDate.

const isSameDay = (a, b) => {
  return a.getFullYear() === b.getFullYear() &&
    a.getMonth() === b.getMonth() &&
    a.getDate()=== b.getDate()
}
const a = new Date(2019, 0, 26, 10) // 26 января 2019, 10:00
const b = new Date(2019, 0, 26, 12) // 26 января 2019, 12:00
console.log(isSameDay(a, b)) // true

Получение даты из другой даты

Чтобы получить дату из другой даты, нужно:

  1. Установить конкретное значение даты/времени из другой даты.
  2. Добавить/вычесть отрезок времени из другой даты.

Установка конкретной даты / времени

Для этого можно использовать следующие методы:

  1. setFullYear: устанавливает четырехзначный год по местному времени.
  2. setMonth: устанавливает месяц года по местному времени.
  3. setDate: устанавливает день месяца по местному времени.
  4. setHours: устанавливает часы по местному времени.
  5. setMinutes: устанавливает минуты по местному времени.
  6. setSeconds: устанавливает секунды по местному времени.
  7. setMilliseconds: устанавливает миллисекунды по местному времени.

Например, если вы хотите задать дату для 15 числа месяца, вы можете использовать метод setDate().

const d = new Date(2019, 0, 10)
d.setDate(15)
console.log(d) // 15 января 2019

Чтобы установить июнь месяц, примените метод setMonth:

const d = new Date(2019, 0, 10)
d.setMonth(5)
console.log(d) // 10 июня 2019

Методы установки значений даты изменяют исходный объект Date(). На практике лучше модифицировать отдельный экземпляр объекта.

const d = new Date(2019, 0, 10)
const newDate = new Date(d)
newDate.setMonth(5)
console.log(d) // 10 января 2019
console.log(newDate) // 10 июня 2019

Добавление/вычитание периода времени из другой даты

Чтобы добавить/вычесть период времени, нужно знать значение текущей даты. Его можно получить с помощью следующих методов:

  1. getFullYear: возвращает четырехзначный год по местному времени.
  2. getMonth: возвращает месяц года (0-11) по местному времени.
  3. getDate: возвращает день месяца (1-31) по местному времени.
  4. getHours: возвращает часы (0-23) по местному времени.
  5. getMinutes: возвращает минуты (0-59) по местному времени.
  6. getSeconds: возвращает секунды (0-59) по местному времени.
  7. getMilliseconds: возвращает миллисекунды (0-999) по местному времени.

Допустим, что вы хотите назначить свидание через три дня (начиная  с сегодняшнего дня). Предположим, что сегодня 28 марта 2019 года.

Первый подход (установка значения)

// Подразумеваем, что сегодня 28 марта 2019
const today = new Date(2019, 2, 28)

Сначала создаем новый объект Date (чтобы не изменять исходный экземпляр объекта):

const finalDate = new Date(today)

С помощью getDate получаем значение, которое хотим изменить:

const currentDate = today.getDate()

Свидание произойдет через три дня. Поэтому добавляем их к текущей дате:

finalDate.setDate(currentDate + 3)

Полный код для первого подхода:

const today = new Date(2019, 2, 28)
const finalDate = new Date(today)
finalDate.setDate(today.getDate() + 3)
console.log(finalDate) // 31 марта 2019

Второй подход (создание новой даты)

Сначала используем getFullYear, getMonth, getDate и другие методы, пока не получим типа значения, которое мы изменить. Затем мы создаём искомую дату при помощи new Date.

const today = new Date(2019, 2, 28)
// Получение нужных значений
const year = today.getFullYear()
const month = today.getMonh()
const day = today.getDate()
// Создание новой даты
const finalDate = new Date(year, month, day + 3)
console.log(finalDate) // 31 марта 2019

Оба подхода работают.

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

Допустим, мы установили дату на 33 марта 2019 года. (В календаре нет 33 марта). В этом случае JavaScript автоматически переведёт 33 марта во 2 апреля.

// 33е марта => 2е апреля
new Date(2019, 2, 33)

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

33 марта автоматически преобразуется во 2 апреля.

Поэтому не стоит беспокоиться о расчете минут, часов, дней, месяцев при добавлении периода времени. JavaScript делает это автоматически.

// 33е марта => 2е апреля
new Date(2019, 2, 30 + 3)

Автоматическая коррекция даты - 2

30+3=33. 33 марта автоматически преобразуется во 2 апреля.

И это всё, что вам нужно знать о JavaScript-объекте Date.

Вадим Дворниковавтор-переводчик статьи «Everything You Need to Know About Date in JavaScript»