Пошук уроків, статей та іншого контенту
Розглянете внутрішнє представлення дат у JavaScript, часові мітки Unix і діапазон значень об’єкта Date.
У JavaScript дата представлена об’єктом Date. Він не зберігає окремо рік, місяць, день, годину та хвилини як основне значення.
Усередині Date зберігає одне число — кількість мілісекунд від початку Unix-епохи:
1 січня 1970 року, 00:00:00 UTC
Це число називають часовою міткою або timestamp.
Наприклад:
const date = new Date(0);
console.log(date);Результат залежить від часового поясу системи, але дата відповідатиме моменту 1970-01-01T00:00:00.000Z.
Число 0 означає самий початок Unix-епохи. Від’ємні значення позначають моменти до неї:
console.log(new Date(0)); // початок Unix-епохи
console.log(new Date(1000)); // через 1 секунду
console.log(new Date(-1000)); // за 1 секунду до Unix-епохиDateВиклик new Date() без аргументів створює об’єкт із поточними датою та часом:
const now = new Date();
console.log(now);Значення створюється в момент виконання цього рядка, тому під час кожного запуску воно буде іншим.
Якщо передати число, JavaScript сприймає його як кількість мілісекунд від Unix-епохи:
const date = new Date(0);
console.log(date.toISOString());
// 1970-01-01T00:00:00.000ZПриклад для 1 січня 2024 року:
const date = new Date(1704067200000);
console.log(date.toISOString());
// 2024-01-01T00:00:00.000ZDate може створюватися з рядка, що відповідає стандартному формату ISO 8601:
const date = new Date("2024-05-20T12:30:00Z");
console.log(date.toISOString());
// 2024-05-20T12:30:00.000ZЛітера Z наприкінці означає UTC — всесвітній координований час.
Можна вказати часовий пояс явно:
const date = new Date("2024-05-20T12:30:00+03:00");
console.log(date.toISOString());
// 2024-05-20T09:30:00.000ZУ цьому прикладі місцевий час 12:30 у часовому поясі UTC+03:00 відповідає 09:30 за UTC.
Для передбачуваної поведінки краще використовувати повні ISO-рядки з часовим поясом:
const date = new Date("2024-05-20T12:30:00Z");Unix timestamp зазвичай вимірюють у секундах, а Date у JavaScript — у мілісекундах.
Це важлива відмінність:
const seconds = 1704067200;
const milliseconds = 1704067200000;
console.log(new Date(seconds).toISOString());
// 1970-01-20T...
console.log(new Date(milliseconds).toISOString());
// 2024-01-01T00:00:00.000ZЧасова мітка 1704067200 — це секунди, а конструктор Date очікує мілісекунди. Тому під час перетворення Unix timestamp у Date секунди потрібно помножити на 1000:
const unixSeconds = 1704067200;
const date = new Date(unixSeconds * 1000);
console.log(date.toISOString());
// 2024-01-01T00:00:00.000ZЩоб отримати Unix timestamp у секундах із поточної дати:
const timestampInSeconds = Math.floor(Date.now() / 1000);
console.log(timestampInSeconds);Date.now()Метод Date.now() повертає поточну часову мітку в мілісекундах:
const timestamp = Date.now();
console.log(timestamp);Це число можна передати в new Date():
const timestamp = Date.now();
const date = new Date(timestamp);
console.log(date.toISOString());Date.now() повертає число, а не об’єкт Date. Якщо потрібен саме об’єкт, використовуйте:
const date = new Date();Метод getTime() повертає кількість мілісекунд від Unix-епохи:
const date = new Date("2024-01-01T00:00:00Z");
console.log(date.getTime());
// 1704067200000Також об’єкт Date автоматично перетворюється на timestamp у числовому контексті:
const date = new Date("2024-01-01T00:00:00Z");
console.log(Number(date));
console.log(date.valueOf());Найзрозуміліше для читання коду використовувати getTime().
Часова мітка однозначно описує момент часу. Проте під час виведення цей момент можна показати:
у UTC;
у часовому поясі локальної системи.
Метод toISOString() завжди повертає дату в UTC:
const date = new Date("2024-01-01T12:00:00Z");
console.log(date.toISOString());
// 2024-01-01T12:00:00.000ZМетод toString() зазвичай показує дату в локальному часовому поясі операційної системи:
console.log(date.toString());Точний результат залежить від налаштувань комп’ютера або середовища виконання.
Для передачі дат між сервером і клієнтом зручно використовувати ISO-формат та UTC:
const date = new Date();
const serialized = date.toISOString();
console.log(serialized);
const restoredDate = new Date(serialized);
console.log(restoredDate.getTime() === date.getTime());
// trueDateОб’єкт Date може представляти часові мітки приблизно від:
-8 640 000 000 000 000 мілісекунд;
до 8 640 000 000 000 000 мілісекунд.
Це приблизно 100 мільйонів днів до та після 1 січня 1970 року.
Максимальний абсолютний timestamp можна отримати через константу 8.64e15:
const minimumDate = new Date(-8.64e15);
const maximumDate = new Date(8.64e15);
console.log(minimumDate.toISOString());
console.log(maximumDate.toISOString());Значення за межами цього діапазону є недійсними:
const invalidDate = new Date(8.64e15 + 1);
console.log(invalidDate.toString());
// Invalid DateЩоб перевірити, чи є дата дійсною, потрібно перевірити її часову мітку:
function isValidDate(date) {
return date instanceof Date && !Number.isNaN(date.getTime());
}
console.log(isValidDate(new Date()));
console.log(isValidDate(new Date("неправильна дата")));Результат:
true
falseНедійсна дата має значення NaN:
const invalidDate = new Date("неправильна дата");
console.log(invalidDate.getTime());
// NaNОб’єкти Date можна порівнювати за допомогою операторів порівняння. JavaScript порівнює їхні часові мітки:
const firstDate = new Date("2024-01-01T00:00:00Z");
const secondDate = new Date("2024-01-02T00:00:00Z");
console.log(firstDate < secondDate);
// trueТакож можна порівнювати timestamp явно:
const firstDate = new Date("2024-01-01T00:00:00Z");
const secondDate = new Date("2024-01-01T00:00:00Z");
console.log(firstDate.getTime() === secondDate.getTime());
// trueНе слід порівнювати два об’єкти Date за допомогою ===, якщо потрібно перевірити однаковий момент часу:
const firstDate = new Date("2024-01-01T00:00:00Z");
const secondDate = new Date("2024-01-01T00:00:00Z");
console.log(firstDate === secondDate);
// falseЦе різні об’єкти в пам’яті, хоча вони представляють той самий момент.
Оскільки Date зберігає мілісекунди, різницю між датами можна отримати відніманням:
const start = new Date("2024-01-01T00:00:00Z");
const end = new Date("2024-01-03T12:00:00Z");
const differenceInMilliseconds = end - start;
const differenceInSeconds = differenceInMilliseconds / 1000;
const differenceInHours = differenceInMilliseconds / (1000 * 60 * 60);
console.log(differenceInMilliseconds);
console.log(differenceInSeconds);
console.log(differenceInHours);
// 60У цьому прикладі між датами 60 годин.
Щоб обчислити кількість повних днів:
const start = new Date("2024-01-01T00:00:00Z");
const end = new Date("2024-01-03T12:00:00Z");
const millisecondsPerDay = 1000 * 60 * 60 * 24;
const fullDays = Math.floor((end - start) / millisecondsPerDay);
console.log(fullDays);
// 2Під час складних обчислень потрібно враховувати переходи на літній або зимовий час. Тривалість локальної календарної доби не завжди дорівнює рівно 24 годинам.
Програма нижче:
отримує поточний час;
перетворює його на Unix timestamp у секундах;
відновлює дату з timestamp;
перевіряє, чи дата дійсна;
обчислює час від початку Unix-епохи.
const now = new Date();
const timestampInMilliseconds = now.getTime();
const timestampInSeconds = Math.floor(timestampInMilliseconds / 1000);
console.log("Поточна дата:", now.toISOString());
console.log("Timestamp у мілісекундах:", timestampInMilliseconds);
console.log("Timestamp у секундах:", timestampInSeconds);
const restoredDate = new Date(timestampInSeconds * 1000);
console.log("Відновлена дата:", restoredDate.toISOString());
console.log("Дата дійсна:", !Number.isNaN(restoredDate.getTime()));
const millisecondsPerDay = 1000 * 60 * 60 * 24;
const daysFromEpoch = Math.floor(timestampInMilliseconds / millisecondsPerDay);
console.log("Повних днів від Unix-епохи:", daysFromEpoch);const unixSeconds = 1704067200;
// Неправильно: Date очікує мілісекунди
const wrongDate = new Date(unixSeconds);
// Правильно: перетворюємо секунди на мілісекунди
const correctDate = new Date(unixSeconds * 1000);===const first = new Date("2024-01-01T00:00:00Z");
const second = new Date("2024-01-01T00:00:00Z");
console.log(first === second);
// false
console.log(first.getTime() === second.getTime());
// trueРезультат аналізу неправильного рядка не завжди очевидний. Перевіряйте getTime():
const date = new Date("2024-99-99");
if (Number.isNaN(date.getTime())) {
console.log("Дата недійсна");
}Рядки на кшталт "01/02/2024" можуть трактуватися по-різному в різних середовищах або культурах.
Надійніше використовувати ISO-формат:
const date = new Date("2024-02-01T00:00:00Z");Дата "2024-01-01T12:00:00Z" і дата "2024-01-01T12:00:00+03:00" описують різні моменти часу.
Якщо часовий пояс важливий, вказуйте його явно.
Date зберігає момент часу як кількість мілісекунд від 1 січня 1970 року за UTC.
Часова мітка 0 відповідає початку Unix-епохи.
Від’ємні timestamp позначають моменти до 1970 року.
Date.now() повертає поточний timestamp у мілісекундах.
getTime() перетворює об’єкт Date на timestamp.
Unix timestamp часто записують у секундах, тому його потрібно помножити на 1000 перед передаванням у Date.
toISOString() повертає дату у стандартному UTC-форматі.
Максимальний підтримуваний діапазон Date приблизно дорівнює ±8.64e15 мілісекунд.
Недійсна дата має timestamp NaN.
Для порівняння дат використовуйте getTime() або оператори порівняння, а не === між об’єктами.