-1

I want to create simple countdown project, where there is targeted date, and I have to count how many days, hours, minutes and seconds left until that date from now. When I test my code with setInterval() it shows up in console, thus it works, but why setInterval do not change time on screen in every second?

// Variables DOM
const days = document.getElementById('day')
const hours = document.getElementById('hour')
const minutes = document.getElementById('minute')
const seconds = document.getElementById('second')
const endDateDisplay = document.getElementById('endDateDisplay');

// Static DB for days and months
const daysList = [
    'Monday',
    'Sunday',
    'Tuesday',
    'Wednesday',
    'Thursday',
    'Friday',
    'Saturday',
    'Sunday'
]

const monthsList = [
    'January', 'February', 'March', 'April', 'May', 'June', 'Jule', 'August', 'September', 'October', 'November', 'December'
]

// Declare present and targeted date
const startDate = new Date();
const endDate = new Date('05/08/2021/03:00');

function displayScreen() {
    // Difference between today and targeted time in milliseconds
    let remainingTime = endDate.getTime() - startDate.getTime();
    // For easier solution turning measure from ms to seconds
    let measureDifferInSeconds = parseInt(remainingTime / 1000);
    // Finding how much days, hours, mins and seconds left until targeted time, after sub respectively
    const leftDays = measureDifferInSeconds / 60 / 60 / 24;
    measureDifferInSeconds = measureDifferInSeconds - Math.floor(leftDays) * 60 * 60 * 24
    const leftHours = measureDifferInSeconds / 60 / 60;
    measureDifferInSeconds = measureDifferInSeconds - Math.floor(leftHours) * 60 * 60;
    const leftMins = measureDifferInSeconds / 60;
    measureDifferInSeconds = measureDifferInSeconds - Math.floor(leftMins) * 60;
    const leftSec = measureDifferInSeconds;

    // Left Time Display for zeros
    if (leftDays < 10) {
        days.innerHTML = "0" + Math.floor(leftDays) + ":";
    } else {
        days.innerHTML = Math.floor(leftDays) + ":";
    }
    if (leftHours < 10) {
        hours.innerHTML = "0" + Math.floor(leftHours) + ":";
    } else {
        hours.innerHTML = Math.floor(leftHours) + ":";
    } if (leftMins < 10) {
        minutes.innerHTML = "0" + Math.floor(leftMins) + ":";
    } else {
        minutes.innerHTML = Math.floor(leftMins) + ":";
    } if (leftSec < 10) {
        seconds.innerHTML = "0" + Math.floor(leftSec);
    } else {
        seconds.innerHTML = Math.floor(leftSec);
    }

    // End Date display for zeros
    let endHourZeroCheck = ''
    let endMinZeroCheck = ''
    if (endDate.getHours() < 10) {
        endHourZeroCheck = '0' + endDate.getHours();
    } else {
        endHourZeroCheck = endDate.getHours()
    }
    if (endDate.getMinutes() < 10) {
        endMinZeroCheck = '0' + endDate.getMinutes();
    } else {
        endMinZeroCheck = endDate.getMinutes()
    }
    endDateDisplay.innerHTML = `${daysList[endDate.getDay()]}, ${endDate.getDate()} ${monthsList[endDate.getMonth()]}, ${endDate.getFullYear()}, ${endHourZeroCheck}:${endMinZeroCheck}`
    console.log('set timeout call');
}

setInterval(displayScreen, 1000)
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Repeat session: Reviews</title>
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css"
    integrity="sha512-iBBXm8fW90+nuLcSKlbmrPcLa0OT92xO1BIsZ+ywDWZCvqsWgccV3gFoRBv0z+8dLJgyAHIhR35VZc2oM/gI1w=="
    crossorigin="anonymous" />
  <!-- STYLE -->
  <link rel="stylesheet" href="style/bc-ui.css">
  <link rel="stylesheet" href="style/main.css" />
  <!-- SCRIPT  -->

  <script src="scripts/app.js" defer></script>
</head>

<body>
  <h2>It ends on <span id='endDateDisplay'></span> </h2>
  <hr>
  <div class="wrapper">
    <h2 id="day">00:</h2>
    <h2 id='hour'>00:</h2>
    <h2 id='minute'>00:</h2>
    <h2 id="second">00</h2>
  </div>
</body>

</html>
Enzoenzo
  • 67
  • 8
  • because `remainingTime` is not `endDate - startDate` but `endDate - now` – Thomas Apr 30 '21 at 23:37
  • Note: as per "[How can I pad a value with leading zeros?](https://stackoverflow.com/a/1267338/90527)", you might be able to use [`String.padStart()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padStart) to pad with leading zeros. – outis Apr 30 '21 at 23:46
  • 1
    Cleaned up your computation a bit: `const lz = v => Math.floor(v).toString().padStart(2,0); const time = endDate - Date.now(); days.textContent = lz(time / 86400000) + ":"; hours.textContent = lz(time / 3600000 % 24) + ":"; minutes.textContent = lz(time / 60000 % 60) + ":"; seconds.textContent = lz(time / 1000 % 60);` – Thomas Apr 30 '21 at 23:57
  • 1
    @Quentin, I'm not sure how this is a duplicate of that Question. The issue here ain't that some Element is not found, but that the "updates" always render the same values to the DOM. – Thomas May 01 '21 at 00:01
  • @Thomas I am a newbie, and because of such 'guys' I hestitate to ask question, they just put negative and sends me to another big, complex links each time. I'm not a native english speaker and explaining my problem is difficult in my own language also. – Enzoenzo May 01 '21 at 00:05
  • @Thomas I do not understand everything that you wrote about computation. I know that you optimized my code, but what this code means? const lz = v => Math.floor(v).toString().padStart(2,0); And where did you get these big numbers(e.g. 86400000)? I just understand that Date.now() much easier, as it directly returns in milliseconds – Enzoenzo May 01 '21 at 00:15
  • 1
    @UlviEnzo The first thing is a utility function to add a leading zero if necessary (`lz`). About the syntax: [MDN arrow functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions). And the big numbers: `86400000 === 1000*60*60*24` – Thomas May 01 '21 at 00:22

1 Answers1

1

If you examine the process in a debugger, you'll note that everything is getting updated, it's just that remainingTime always has the same value. Since startDate and endDate are set once and do not change after the initial load, remainingTime has the same value each time displayScreen is run.

outis
  • 75,655
  • 22
  • 151
  • 221
  • Oh, thanks, when I put startDate and endDate inside function it worked. – Enzoenzo May 01 '21 at 00:02
  • @UlviEnzo: no need for `endDate` to be in the function, as its value is constant. Only values that change for each invocation of a block (e.g. function body, loop body) should go in the block. "Invariant values" (values that don't change for each block invocation) should go outside the block. This is one of the applications of the [loop invariant](https://en.wikipedia.org/wiki/Loop_invariant) concept. – outis May 01 '21 at 00:11