Search code examples
javascriptsetintervalcountdowntimerclearinterval

Why is my date object returning back NaN values?


My program is supposed to start a countdown timer that calculates the time remaining in days, hours, seconds, etc from today till the the date that the user picks in the input field.

While the program updates the HTML with the correct time remaining, the problem starts when I try to update countdown timer every second. It returns back NaN values for some reason. Why is that??

Here's my JS:

const input = document.querySelector('input')
let timeInterval;
let timeStop;


input.addEventListener('change', (e) => {
    e.preventDefault()
    timeStop = true;
    endTime = Date.parse(e.target.value)
    updateHTML(endTime)
})


function updateHTML(endTime) {
  let time = calculateTimeDiff(endTime)
  if (time.total <= 0) {
    timeStop = false;
  }
  for (let pro in time) {
    let el = document.querySelector(`.${pro}`)
    if (el) {
      el.innerHTML = time[pro];
    }
  }
  updateCounter();
}


function updateCounter () {
  if (timeStop) {
    timeInterval = setInterval(updateHTML, 1000);
  } else {
    clearInterval(timeInterval);
  }
}

//returning time remaining till date in object form 
function calculateTimeDiff(endTime) {
  let start = Date.now();
  let end = endTime;
  let t = (end-start);
  let seconds = Math.floor((t / 1000) % 60);
  let minutes = Math.floor((t / 1000 / 60) % 60);
  let hours = Math.floor((t / (1000 * 60 * 60)) % 24);
  let days = Math.floor(t / (1000 * 60 * 60 * 24));
  return {
    total: t,
    days: days,
    hours: hours,
    minutes: minutes,
    seconds: seconds
  }
}

Solution

  • So your code works fine but your problem is with your endTime. In your setInterval, you are calling updateHTML without the parameter endTime so that causes an error as it doesn't have a reference for the param.

    You can either simply update your updateCounter function to accept this as a parameter and pass it to your setInterval function:

    function updateCounter (endTime) {
      if (timeStop) {
        timeInterval=setInterval(() => updateHTML(endTime), 1000)
      } else {
        clearInterval(timeInterval)
      }
    }
    

    and then call updateCounter with the endTime at the bottom of your updateHtml function.

    Or, remove endTime as a parameter from updateHtml and make it a global variable:

    const input=document.querySelector('input')
    let timeInterval;
    let timeStop;
    let endTime;
    
    
    input.addEventListener('change', (e)=> {
      e.preventDefault()
      timeStop=true;
      endTime=Date.parse(e.target.value)
      updateHTML()
    })
    
    
    function updateHTML () {
      let time=calculateTimeDiff(endTime)
      if (time.total<=0) {
        timeStop=false
      }
      for (let pro in time) {
        let el=document.querySelector(`.${pro}`)
        if (el) {
          el.innerHTML=time[pro]
        }
      }
      updateCounter()
    }
    
    
    etc...