24 вересня 2024 р.

Дата і час

Познайомтеся з новим вбудованим об’єктом: Date. Він зберігає дату, час і надає методи для управління датою/часом.

Наприклад, ми можемо використовувати його для зберігання часу створення/модифікації, щоб виміряти час, або просто для друку поточної дати.

Створення

Щоб створити новий об’єкт Date викличемо new Date() з одним з наступних аргументів:

new Date()

Без аргументів – створює об’єкт Date для поточної дати та часу:

let now = new Date();
alert( now ); // показує поточну дату/час
new Date(milliseconds)

Створює об’єкт Date з часом, що дорівнює кількості мілісекунд (1/1000 секунди), що минули після 1 січня 1970 UTC+0.

// 0 означає 01.01.1970 UTC+0
let Jan01_1970 = new Date(0);
alert( Jan01_1970 );

// тепер додамо 24 години, отримаємо 02.01.1970 UTC+0
let Jan02_1970 = new Date(24 * 3600 * 1000);
alert( Jan02_1970 );

Ціле число, яке являє собою кількість мілісекунд, що пройшли з початку 1970 року, називається міткою часу (timestamp).

Це легке числове представлення дати. Ми завжди можемо створити дату з timestamp за допомогою new Date(timestamp) і перетворити об’єкт Date, що існує, до timestamp за допомогою методу date.getTime() (див. нижче).

Дати до 01.01.1970 р. мають негативний timestamp, наприклад:

// 31 грудня 1969 року
let Dec31_1969 = new Date(-24 * 3600 * 1000);
alert( Dec31_1969 );
new Date(datestring)

Якщо є єдиний аргумент, і це рядок, то він автоматично аналізується. Алгоритм той же, що використовує Date.parse, ми розглянемо це пізніше.

let date = new Date("2017-01-26");
alert(date);
// Час не встановлений, тому припускається, що це буде північ за GMT і
// регулюється відповідно до того часового поясу, де запускається код
// Тому результат може бути
// Thu Jan 26 2017 11:00:00 GMT+1100 (Australian Eastern Daylight Time)
// або
// Wed Jan 25 2017 16:00:00 GMT-0800 (Pacific Standard Time)
new Date(year, month, date, hours, minutes, seconds, ms)

Створює дату з заданими компонентами у місцевому часовому поясі. Тільки перші два аргументи обов’язкові.

  • year має містити 4 цифри. Для сумісності також допускаються 2 цифри, які вважаються 19xx, напр. 98 тут те саме, що й 1998, але настійно рекомендується завжди використовувати 4 цифри.
  • Рахунок місяців починається з 0 (січня), до 11 (грудня).
  • Параметр date насправді день місяця, якщо він відсутній, то береться 1.
  • Якщо hours/minutes/seconds/ms відсутні, вони вважаються рівними 0.

Наприклад:

new Date(2011, 0, 1, 0, 0, 0, 0); // 1 січня 2011 року, 00:00:00
new Date(2011, 0, 1); // те ж саме, години тощо -- 0 за замовчуванням

Максимальна точність становить 1 мс (1/1000 сек):

let date = new Date(2011, 0, 1, 2, 3, 4, 567);
alert( date ); // 1.01.2011, 02:03:04.567

Доступ до компонентів дати

Існують методи доступу до року, місяця і так далі з об’єкта Date:

getFullYear()
Отримати рік (4 цифри)
getMonth()
Отримати місяць, від 0 до 11.
getDate()
Отримати день місяця, від 1 до 31, назва методу виглядає трохи дивно.
getHours(), getMinutes(), getSeconds(), getMilliseconds()
Отримати відповідні компоненти часу.
Не getYear(), а getFullYear()

Багато рушіїв JavaScript реалізують нестандартний метод getYear(). Цей метод застарілий. Іноді він повертає 2-значний рік. Будь ласка, не використовуйте його. Щоб отримати рік є getFullYear().

Крім того, ми можемо отримати день тижня:

getDay()
Отримати день тижня, від 0 (неділя) до 6 (субота). Перший день завжди неділя, в деяких країнах це не так, але ми не можемо змінити поведінку методу.

Всі методи, наведені вище, повертають компоненти відносно місцевого часового поясу.

Є також їхні UTC-аналоги, що повертається день, місяць, рік і так далі за часовим поясом UTC+0: getUTCFullYear(), getUTCMonth(), getUTCDay(). Просто вставте "UTC" відразу після "get".

Якщо ваш місцевий часовий пояс зміщений відносно UTC, то код нижче показує різні години:

// поточна дата
let date = new Date();

// години у поточному часовому поясі
alert( date.getHours() );

// години у часовій зоні UTC+0 (Лондонський час без літніх переводів часу)
alert( date.getUTCHours() );

Окрім наведених методів, є два спеціальних, які не мають UTC-варіанту:

getTime()

Повертає timestamp для дати – кількість мілісекунд, що пройшли з 1 січня 1970 UTC+0.

getTimezoneOffset()

Повертає різницю між UTC та місцевим часовим поясом, у хвилинах:

// якщо ви знаходитесь в часовому поясі UTC-1 -- видасть 60
// якщо ви знаходитесь в часовому поясі UTC+3 -- видасть -180
alert( new Date().getTimezoneOffset() );

Налаштування компонентів дати

Наступні методи дозволяють встановити дату/часові компоненти:

Кожен з них, крім setTime() має UTC-аналог, наприклад: setUTCHours().

Як ми бачимо, деякі методи можуть встановити кілька компонентів відразу, наприклад setHours. Компоненти дати/часу, які не згадуються, – не модифікуються.

Наприклад:

let today = new Date();

today.setHours(0);
alert(today); // ще сьогодні, але година змінюється на 0

today.setHours(0, 0, 0, 0);
alert(today); // ще сьогодні, зараз рівно 00:00:00.

Автокорекція

Автокорекція – це дуже зручна особливість об’єктів Date. Ми можемо встановити данні за межами діапазону, і вони будуть автоматично налаштувати себе.

Наприклад:

let date = new Date(2013, 0, 32); // 32 січня 2013 ?!?
alert(date); // ...це 1 лютого 2013!

Компоненти поза межами діапазону розподіляються автоматично.

Скажімо, нам потрібно збільшити дату “28 лютого 2016” на 2 дні. Це може бути “2 березня” або “1 березня” у випадку високосного року. Нам не потрібно думати про це. Просто додайте 2 дні. Об’єкт Date зробить все інше:

let date = new Date(2016, 1, 28);
date.setDate(date.getDate() + 2);

alert( date ); // 1 березня 2016

Ця особливість часто використовується для отримання дати після певного проміжку часу. Наприклад, отримаймо дату “70 секунд після зараз”:

let date = new Date();
date.setSeconds(date.getSeconds() + 70);

alert( date ); // показує правильну дату

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

let date = new Date(2016, 0, 2); // 2 січня 2016

date.setDate(1); // встановити 1 день місяця
alert( date );

date.setDate(0); // мінімальний номер дня -- 1, тому передбачається, що це останній день попереднього місяця
alert( date ); // 31 грудня 2015

Перетворення дати до числа, різниця дат

Коли Date об’єкт перетворюється на номер, він стає timestamp так само, як date.getTime():

let date = new Date();
alert(+date); // кількість мілісекунд, так само, як date.getTime()

Важливий побічний ефект: дати можуть відніматися, результатом є їх різниця в мілісекундах.

Це можна використовувати для вимірювання часу:

let start = new Date(); // початок вимірювання часу

// виконується робота
for (let i = 0; i < 100000; i++) {
  let doSomething = i * i * i;
}

let end = new Date(); // кінець вимірювання часу

alert( `Цикл зайняв ${end - start} мс` );

Date.now()

Якщо ми хочемо тільки виміряти час, нам не потрібен об’єкт Date.

Існує спеціальний метод Date.now(), що повертає поточний timestamp.

Це семантично еквівалентно до new Date().getTime(), але не створює проміжного об’єкта Date. Так що цей підхід працює швидше і не навантажує збирач сміття.

Він використовується в основному для зручності або коли важлива продуктивність, як в іграх на JavaScript або інших спеціалізованих застосунках.

Отже, це, мабуть, краще:

let start = Date.now(); // кількість мілісекунд з 1 січня 1970 року

// виконується робота
for (let i = 0; i < 100000; i++) {
  let doSomething = i * i * i;
}

let end = Date.now(); // готово

alert( `Цикл зайняв ${end - start} мс` ); // віднімемо цифри, а не дати

Вимірювання швидкодії (Benchmarking)

Якщо ми хочемо достовірний аналіз швидкодії функції, що залежить від процесора, ми повинні бути обережними.

Наприклад, давайте вимірюємо дві функції, які обчислюють різницю між двома датами: яка з них швидше?

Такі вимірювання продуктивності часто називаються “бенчмарками”.

// У нас є date1 і date2. Яка функція швидше поверне їхню різницю в мс?
function diffSubtract(date1, date2) {
  return date2 - date1;
}

// чи
function diffGetTime(date1, date2) {
  return date2.getTime() - date1.getTime();
}

Ці дві функції роблять схожі речі, але одна з них використовує явний date.getTime(), щоб отримати дату в мс, а інша покладається на перетворення дати до числа. Їх результат завжди однаковий.

Отже, яка з цих функцій швидша?

Перша ідея полягає в тому, що можна багато разів запустити їх поспіль і виміряти різницю часу. Для нашого випадку функції дуже прості, тому ми повинні запустити їх щонайменше 100000 разів.

Вимірюємо:

function diffSubtract(date1, date2) {
  return date2 - date1;
}

function diffGetTime(date1, date2) {
  return date2.getTime() - date1.getTime();
}

function bench(f) {
  let date1 = new Date(0);
  let date2 = new Date();

  let start = Date.now();
  for (let i = 0; i < 100000; i++) f(date1, date2);
  return Date.now() - start;
}

alert( 'Час diffSubtract: ' + bench(diffSubtract) + 'мс' );
alert( 'Час diffGetTime: ' + bench(diffGetTime) + 'мс' );

Оце так! Використання getTime() набагато швидше! Це тому, що немає перетворення типу, це набагато простіше для оптимізації.

Гаразд, у нас є щось. Але це ще не хороший бенчмарк.

Уявіть собі, що під час запуску bench(diffSubtract) процесор робив щось паралельно, і це забирало певні ресурси. І до часу роботи bench(diffGetTime) ця робота закінчилася.

Досить реальний сценарій для сучасної багатопроцесорної ОС.

Як результат, перший бенчмарк буде мати менше ресурсів процесора, ніж другий. Це може призвести до неправильних результатів.

Для більш достовірного порівняльного аналізу, весь пакет бенчмарків повинен бути повторно запущений кілька разів.

Наприклад, як це:

function diffSubtract(date1, date2) {
  return date2 - date1;
}

function diffGetTime(date1, date2) {
  return date2.getTime() - date1.getTime();
}

function bench(f) {
  let date1 = new Date(0);
  let date2 = new Date();

  let start = Date.now();
  for (let i = 0; i < 100000; i++) f(date1, date2);
  return Date.now() - start;
}

let time1 = 0;
let time2 = 0;

// запустіть bench(diffSubtract) і bench(diffGetTime) кожен по 10 разів
for (let i = 0; i < 10; i++) {
  time1 += bench(diffSubtract);
  time2 += bench(diffGetTime);
}

alert( 'Загальний час для diffSubtract: ' + time1 );
alert( 'Загальний час для diffGetTime: ' + time2 );

Сучасні рушії JavaScript починають застосовувати передові оптимізації лише до “гарячого коду”, який виконує багато разів (не потрібно оптимізувати рідко виконані речі). Отже, у наведеному вище прикладі перші виконання не оптимізовані. Ми можемо захотіти додати “нагрівання”:

// додано для "нагрівання" до основного циклу
bench(diffSubtract);
bench(diffGetTime);

// тепер бенчмарк
for (let i = 0; i < 10; i++) {
  time1 += bench(diffSubtract);
  time2 += bench(diffGetTime);
}
Будьте обережні, що робить мікробенчмаркінг

Сучасні рушії JavaScript застосовують багато оптимізацій. Вони можуть підналаштувати результати “штучних тестів” у порівнянні з “нормальним використанням”, особливо коли ми тестуємо щось дуже мале, наприклад, як працює оператор, або вбудована функція. Отже, якщо ви серйозно хочете оцінити продуктивність, то, будь ласка, дослідіть, як працює рушій JavaScript. І тоді ви, мабуть, не потребуєте мікробенчмаркінгів взагалі.

Великий набір статей про V8 можна знайти на https://mrale.ph.

Date.parse з рядка

Метод Date.parse(str) може читати дату з рядка.

Формат рядка повинен бути: YYYY-MM-DDTHH:mm:ss.sssZ, де:

  • YYYY-MM-DD – це дата: рік-місяць-день.
  • Символ "T" використовується як роздільник.
  • HH:mm:ss.sss – це час: години, хвилини, секунди і мілісекунди.
  • Необов’язкова частина 'Z' позначає часовий пояс у форматі +-hh:mm. Одинична буква Z буде означати UTC+0.

Коротші варіанти також можливі, як YYYY-MM-DD або YYYY-MM або навіть YYYY.

Виклик Date.parse(str) аналізує рядок у заданому форматі та повертає timestamp (кількість мілісекунд з 1 січня 1970 UTC+0). Якщо формат недійсний, повертає NaN.

Наприклад:

let ms = Date.parse('2012-01-26T13:51:50.417-07:00');

alert(ms); // 1327611110417  (timestamp)

Ми можемо миттєво створити об’єкт за допомогою new Date з timestamp:

let date = new Date( Date.parse('2012-01-26T13:51:50.417-07:00') );

alert(date);

Підсумки

  • Дата та час у JavaScript представлені об’єктом Date. Ми не можемо створити “тільки дату” або “тільки час”: об’єкти Date завжди несуть в собі обидва значення.
  • Місяці рахуються з нуля (так, січень – це нульовий місяць).
  • Дні тижня в getDay() також рахуються з нуля (з неділі).
  • Date автоматично виправляє себе, коли встановлено компоненти, які виходять за межі. Це добре для додавання/віднімання днів/місяців/годин.
  • Дати можуть відніматися, даючи їхню різницю в мілісекундах. Це тому, що Date стає timestamp, коли перетворюється на число.
  • Використовуйте Date.now(), щоб швидко отримати поточний timestamp.

Зауважте, що на відміну від багатьох інших систем, значенния timestamp в JavaScript вимірюється в мілісекундах, а не в секундах.

Іноді нам потрібно більш точні вимірювання часу. Сам JavaScript не має способу вимірювання часу в мікросекундах (1 мільйон у секунду), але більшість середовищ забезпечують його. Наприклад, браузер має performance.now(), що дає кількість мілісекунд з початку завантаження сторінки з мікросекундною точністю (3 цифри після крапки):

alert(`Завантаження почалося ${performance.now()}мс тому`);
// Щось на зразок: "Завантаження почалося 34731.26000000001мс тому"
// .26 це мікросекунди (260 мікросекунд)
// коректними є тільки перші три цифри після крапки, а решта -- це помилка точності

Node.js має модуль microtime та інші способи. Технічно, майже будь-який пристрій та середовище дозволяє отримати більшу точність, просто її немає в Date.

Завдання

важливість: 5

Створити об’єкт Date на дату: 20 лютого 2012, 3:12 ранку. Часовий пояс є місцевим.

Показати його за допомогою alert.

Конструктор new Date використовує місцевий часовий пояс. Отже, єдина важлива річ, яку слід пам’ятати це те, що місяці починаються з нуля.

Тому лютий має номер 1.

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

//new Date(year, month, date, hour, minute, second, millisecond)
let d1 = new Date(2012, 1, 20, 3, 12);
alert( d1 );

Ми також можемо створити дату з рядка, як наприклад:

//new Date(datastring)
let d2 = new Date("2012-02-20T03:12");
alert( d2 );
важливість: 5

Напишіть функцію getWeekDay(date), щоб показати день тижня у короткому форматі: ‘ПН’, ‘ВТ’, ‘СР’, ‘ЧТ’, ‘ПТ’, ‘СБ’, ‘НД’.

Наприклад:

let date = new Date(2012, 0, 3);  // 3 січня 2012
alert( getWeekDay(date) );        // повинно виводити "ВТ"

Відкрити пісочницю з тестами.

Метод date.getDay() повертає номер дня тижня, починаючи з неділі.

Зробімо масив днів тижня, щоб ми могли отримати відповідну назву дня за номером:

function getWeekDay(date) {
  let days = ['НД', 'ПН', 'ВТ', 'СР', 'ЧТ', 'ПТ', 'СБ'];

  return days[date.getDay()];
}

let date = new Date(2014, 0, 3); // 3 січня 2014
alert( getWeekDay(date) ); // ПТ

Відкрити рішення із тестами в пісочниці.

важливість: 5

Європейські країни мають дні тижня, що починаються з понеділка (№ 1), потім вівторок (№ 2) та до неділі (№ 7). Напишіть функцію getLocalDay(date), що повертає “європейський” день тижня для date.

let date = new Date(2012, 0, 3);  // 3 січня 2012
alert( getLocalDay(date) );       // вівторок, слід показати 2

Відкрити пісочницю з тестами.

function getLocalDay(date) {

  let day = date.getDay();

  if (day == 0) { // weekday 0 (sunday) is 7 in european
    day = 7;
  }

  return day;
}

Відкрити рішення із тестами в пісочниці.

важливість: 4

Створіть функцію getDateAgo(date, days), щоб повернути день місяця, який був days днів після date.

Наприклад, якщо сьогодні – 20-й, то getDateAgo(new Date(), 1) має бути 19-го, а getDateAgo(new Date(), 2) має бути 18-го.

Має працювати надійно для days = 365 або більше:

let date = new Date(2015, 0, 2);

alert( getDateAgo(date, 1) ); // 1, (1 січня 2015)
alert( getDateAgo(date, 2) ); // 31, (31 грудня 2014)
alert( getDateAgo(date, 365) ); // 2, (2 січня 2014)

P.S. Функція не повинна змінювати date.

Відкрити пісочницю з тестами.

Ідея проста: відняти від date дане число кількості днів:

function getDateAgo(date, days) {
  date.setDate(date.getDate() - days);
  return date.getDate();
}

…Але функція не повинна змінювати date. Це важливо, тому що зовнішній код, який дає нам дату, не очікує, що вона зміниться.

Щоб реалізувати це, клонуймо дату, наступним чином:

function getDateAgo(date, days) {
  let dateCopy = new Date(date);

  dateCopy.setDate(date.getDate() - days);
  return dateCopy.getDate();
}

let date = new Date(2015, 0, 2);

alert( getDateAgo(date, 1) ); // 1, (1 січня 2015)
alert( getDateAgo(date, 2) ); // 31, (31 грудня 2014)
alert( getDateAgo(date, 365) ); // 2, (2 січня 2014)

Відкрити рішення із тестами в пісочниці.

важливість: 5

Напишіть функцію getLastDayOfMonth(year, month), що повертає останній день місяця. Іноді це 30-е, 31-ше або навіть 28/29-е для лютого.

Параметри:

  • year – чотиризначний рік, наприклад 2012.
  • month – місяць, від 0 to 11.

Наприклад, getLastDayOfMonth(2012, 1) = 29 (високосний рік, лютий).

Відкрити пісочницю з тестами.

Створімо дату, використовуючи наступний місяць, але передамо нуль, як день:

function getLastDayOfMonth(year, month) {
  let date = new Date(year, month + 1, 0);
  return date.getDate();
}

alert( getLastDayOfMonth(2012, 0) ); // 31
alert( getLastDayOfMonth(2012, 1) ); // 29
alert( getLastDayOfMonth(2013, 1) ); // 28

Зазвичай дати починаються з 1, але технічно ми можемо передати будь-яке число, дата автоматично відрегулює себе. Отже, коли ми передаємо 0, то це означає “за день до 1-го дня місяця”, іншими словами: “останній день попереднього місяця”.

Відкрити рішення із тестами в пісочниці.

важливість: 5

Напишіть функцію getSecondsToday(), що повертає кількість секунд з початку сьогоднішнього дня.

Наприклад, якщо зараз 10:00 am, і не було зміни літнього часу, то:

getSecondsToday() == 36000 // (3600 * 10)

Функція повинна працювати в будь-який день. Тобто, вона не повинна мати жорстко-кодоване значення “сьогодні”.

Щоб отримати кількість секунд, ми можемо створити дату, використовуючи поточний день та час 00:00:00, а потім відняти його від “зараз”.

Різниця – це кількість мілісекунд з початку дня, яку ми повинні розділити на 1000, щоб отримати секунди:

function getSecondsToday() {
  let now = new Date();

  // створити об’єкт, використовуючи поточний день/місяць/рік
  let today = new Date(now.getFullYear(), now.getMonth(), now.getDate());

  let diff = now - today; // мс різниця
  return Math.round(diff / 1000); // зробити секунди
}

alert( getSecondsToday() );

Альтернативне рішення полягає в тому, щоб отримати години/хвилини/секунди та конвертувати їх до секунд:

function getSecondsToday() {
  let d = new Date();
  return d.getHours() * 3600 + d.getMinutes() * 60 + d.getSeconds();
}

alert( getSecondsToday() );
важливість: 5

Створіть функцію getSecondsToTomorrow(), що повертає кількість секунд до завтра.

Наприклад, якщо зараз є 23:00, то:

getSecondsToTomorrow() == 3600

P.S. Функція повинна працювати в будь-який день, “сьогодні” не є жорстко закодованим.

Щоб отримати кількість мілісекунд до завтра, ми можемо від “завтра 00:00:00” відняти поточну дату.

По-перше, ми створюємо це “завтра”, а потім віднімемо:

function getSecondsToTomorrow() {
  let now = new Date();

  // завтрашня дата
  let tomorrow = new Date(now.getFullYear(), now.getMonth(), now.getDate()+1);

  let diff = tomorrow - now; // різниця в мс
  return Math.round(diff / 1000); // перетворити до секунд
}

Alternative solution:

function getSecondsToTomorrow() {
  let now = new Date();
  let hour = now.getHours();
  let minutes = now.getMinutes();
  let seconds = now.getSeconds();
  let totalSecondsToday = (hour * 60 + minutes) * 60 + seconds;
  let totalSecondsInADay = 86400;

  return totalSecondsInADay - totalSecondsToday;
}

Будь ласка, зверніть увагу, що у багатьох країнах є літній час, тому можуть бути дні з 23 або 25 годин. Ми можемо обробляти такі дні окремо.

важливість: 4

Напишіть функцію formatDate(date), яка повинна форматувати date наступним чином:

  • Якщо з date пройшла менше, ніж 1 секунда, то "прямо зараз".
  • Інакше, якщо з date пройшло менше 1 хвилини, то "n сек. назад".
  • Інакше, якщо менше години, то "m хв. назад".
  • В іншому випадку повна дата у форматі "DD.MM.YY HH:mm". Тобто: "день.місяць.рік години:хвилини", все в 2-значному форматі, наприклад, 31.12.16 10:00.

Наприклад:

alert( formatDate(new Date(new Date - 1)) ); // "прямо зараз"

alert( formatDate(new Date(new Date - 30 * 1000)) ); // "30 сек. назад"

alert( formatDate(new Date(new Date - 5 * 60 * 1000)) ); // "5 хв. назад"

// вчорашня дата, як 31.12.16 20:00
alert( formatDate(new Date(new Date - 86400 * 1000)) );

Відкрити пісочницю з тестами.

Щоб отримати час від date дотепер – давайте віднімемо дати.

function formatDate(date) {
  let diff = new Date() - date; // різниця в мілісекундах

  if (diff < 1000) { // менше 1 секунди
    return 'прямо зараз';
  }

  let sec = Math.floor(diff / 1000); // перетворити різницю до секунд

  if (sec < 60) {
    return sec + ' сек. назад';
  }

  let min = Math.floor(diff / 60000); // перетворити різницю до хвилин
  if (min < 60) {
    return min + ' хв. назад';
  }

  // форматувати дату
  // додати нулі до однозначних днів/місяців/годин/хвилин
  let d = date;
  d = [
    '0' + d.getDate(),
    '0' + (d.getMonth() + 1),
    '' + d.getFullYear(),
    '0' + d.getHours(),
    '0' + d.getMinutes()
  ].map(component => component.slice(-2)); // отримати останні 2 цифри кожного компоненту

  // з’єднати компоненти в дату
  return d.slice(0, 3).join('.') + ' ' + d.slice(3).join(':');
}

alert( formatDate(new Date(new Date - 1)) ); // "прямо зараз"

alert( formatDate(new Date(new Date - 30 * 1000)) ); // "30 сек. назад"

alert( formatDate(new Date(new Date - 5 * 60 * 1000)) ); // "5 хв. назад"

// вчорашня дата, як 31.12.2016 20:00
alert( formatDate(new Date(new Date - 86400 * 1000)) );

Альтернативне рішення:

function formatDate(date) {
  let dayOfMonth = date.getDate();
  let month = date.getMonth() + 1;
  let year = date.getFullYear();
  let hour = date.getHours();
  let minutes = date.getMinutes();
  let diffMs = new Date() - date;
  let diffSec = Math.round(diffMs / 1000);
  let diffMin = diffSec / 60;
  let diffHour = diffMin / 60;

  // форматування
  year = year.toString().slice(-2);
  month = month < 10 ? '0' + month : month;
  dayOfMonth = dayOfMonth < 10 ? '0' + dayOfMonth : dayOfMonth;
  hour = hour < 10 ? '0' + hour : hour;
  minutes = minutes < 10 ? '0' + minutes : minutes;

  if (diffSec < 1) {
    return 'прямо зараз';
  } else if (diffMin < 1) {
    return `${diffSec} сек. назад`
  } else if (diffHour < 1) {
    return `${diffMin} хв. назад`
  } else {
    return `${dayOfMonth}.${month}.${year} ${hour}:${minutes}`
  }
}

Відкрити рішення із тестами в пісочниці.

Навчальна карта