JS Countdown Timer with save session to LocalStorage

updated: 31.10.2020

import moment from "moment";
import "moment-timezone";

const promoCountdown = document.querySelector(".s-promo__countdown");

if (promoCountdown) {
  let countdown;
  if (localStorage.getItem("promo_coundown")) {
    countdown = new Date(Number(localStorage.getItem("promo_coundown")));
  } else {
    countdown =
      new Date(
        new Date().toLocaleString("en-US", { timeZone: "Europe/Moscow" })
      ).getTime() +
      3 * 24 * 60 * 60 * 1000;
  }

  function midnightCountdown() {
    if (localStorage.getItem("coundown_reset")) {
      const dateNow = moment(
        new Date(
          new Date().toLocaleString("en-US", { timeZone: "Europe/Moscow" })
        )
      );
      const dateToReset = moment(
        new Date(Number(localStorage.getItem("coundown_reset")))
      );
      const diffDate = dateNow.diff(dateToReset);
      const diffHours = Math.floor(diffDate / (1000 * 60 * 60));

      const startDay = moment(
        new Date(
          new Date().toLocaleString("en-US", { timeZone: "Europe/Moscow" })
        ).setHours(0, 0, 0, 0)
      );

      let diffFromStart = dateNow.diff(startDay);
      diffFromStart = Math.floor(diffFromStart / (1000 * 60 * 60));

      if (diffHours >= 24) {
        countdown =
          new Date(
            new Date().toLocaleString("en-US", { timeZone: "Europe/Moscow" })
          ).getTime() +
          (3 * 24 - diffFromStart) * 60 * 60 * 1000;

        localStorage.setItem("promo_coundown", new Date(countdown).getTime());

        let lastUpdate = new Date(
          new Date().toLocaleString("en-US", { timeZone: "Europe/Moscow" })
        );
        lastUpdate.setDate(lastUpdate.getDate() - 1);
        lastUpdate = lastUpdate.setHours(24, 0, 0, 0);
        localStorage.setItem("coundown_reset", lastUpdate);
      }
    } else {
      let lastUpdate = new Date(
        new Date().toLocaleString("en-US", { timeZone: "Europe/Moscow" })
      );
      lastUpdate.setDate(lastUpdate.getDate() - 1);
      lastUpdate = lastUpdate.setHours(24, 0, 0, 0);
      localStorage.setItem("coundown_reset", lastUpdate);
    }
  }

  function countdownTick() {
    midnightCountdown();
    const dateNow = moment(
      new Date(
        new Date().toLocaleString("en-US", { timeZone: "Europe/Moscow" })
      )
    );
    const dateTo = moment(countdown);
    const diffDate = dateTo.diff(dateNow);

    function msToTime(diff) {
      let seconds = Math.floor((diff / 1000) % 60);
      let minutes = Math.floor((diff / (1000 * 60)) % 60);
      let hours = Math.floor((diff / (1000 * 60 * 60)) % 24);
      let days = Math.floor((diff / (1000 * 60 * 60 * 24)) % 24);

      function declOfNum(number, titles) {
        const cases = [2, 0, 1, 1, 1, 2];
        return titles[
          number % 100 > 4 && number % 100 < 20
            ? 2
            : cases[number % 10 < 5 ? number % 10 : 5]
        ];
      }

      const daysFormat = declOfNum(days, ["день", "дня", "дней"]);
      const hoursFormat = declOfNum(hours, ["час", "часа", "часов"]);
      const minutesFormat = declOfNum(minutes, ["минута", "минуты", "минут"]);
      const secondsFormat = declOfNum(seconds, [
        "секунда",
        "секунды",
        "секунд",
      ]);

      document.querySelector(
        ".s-promo__countdown span"
      ).innerHTML = `${days} ${daysFormat} ${hours} ${hoursFormat} ${minutes} ${minutesFormat} ${seconds} ${secondsFormat}`;
    }

    msToTime(diffDate);

    localStorage.setItem("promo_coundown", new Date(countdown).getTime());
  }

  countdownTick();

  setInterval(() => {
    countdownTick();
  }, 1000);
}