skip to Main Content

I want the Timer to display "Currently streaming" for two hours after the countdown ended, and then to start the next countdown. For some reason that just doesn’t work/the text stays there forever/for way too long.

// Stream slots in UTC (Germany is UTC+2)
const streamTimes = [
  { day: 1, hour: 17, minute: 0 },     // Monday
  { day: 2, hour: 17, minute: 0 },     // Tuesday
  { day: 3, hour: 17, minute: 0 },     // Wednesday
  { day: 4, hour: 17, minute: 0 },     // Thursday
  { day: 5, hour: 18, minute: 0 },     // Friday
  { day: 6, hour: 13, minute: 0 },     // Saturday
];

function getNextStreamTime() {
  const now = new Date();
  const currentDay = now.getUTCDay();
  const currentHour = now.getUTCHours();
  const currentMinute = now.getUTCMinutes();
  
  for (let i = 0; i < streamTimes.length; i++) {
    const streamTime = streamTimes[i];
    if (streamTime.day > currentDay || (streamTime.day === currentDay && streamTime.hour > currentHour) || (streamTime.day === currentDay && streamTime.hour === currentHour && streamTime.minute > currentMinute)) {
      return streamTime;
    }
  }

  // If there are no more stream slots, move on to monday
  return streamTimes[0];
}

function startCountdown() {
  const countdownElement = document.getElementById("countdown");
  
  const nextStreamTime = getNextStreamTime();
  const targetDate = new Date();
  targetDate.setUTCHours(nextStreamTime.hour, nextStreamTime.minute, 0, 0);
  
  const timer = setInterval(() => {
    const currentDate = new Date();
    const timeDifference = targetDate - currentDate;
    
    if (timeDifference <= 0) {
      clearInterval(timer);
      countdownElement.innerHTML = "Currently streaming";
      setTimeout(startCountdown, 2 * 60 * 60 * 1000); 
      return;
    }
    
    const days = Math.floor(timeDifference / (1000 * 60 * 60 * 24));
    const hours = Math.floor((timeDifference % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
    const minutes = Math.floor((timeDifference % (1000 * 60 * 60)) / (1000 * 60));
    const seconds = Math.floor((timeDifference % (1000 * 60)) / 1000);
    
    countdownElement.innerHTML = `${days} days, ${hours} hours, ${minutes} minutes, ${seconds} seconds`;
  }, 1000);
}

startCountdown();

I expected it to work like that and have absolutely no idea why it isn’t working.

2

Answers


  1. So on day=1 you finish streaming at 19:00, then you set the target date to the same day, but at 17:00. Which means that targetDate - currentDate will be less than 0 because you haven’t set targetDate to be the next day, therefore displaying Currently streaming and setting another timer for 2 hours. It isn’t until the next day, that it will actually start working again. Replace:

    const targetDate = new Date(Date.now() + 864E5 * (nextStreamTime.day - new Date().getUTCDay()))
    

    864E5 is the number of milliseconds in a day, so you want to add that to the current date if the target date is tomorrow

    Login or Signup to reply.
  2. I copied your code and made some changes. First, there are a bunch of number calculations representing durations which are repeated multiple times and then re-calculated once a second. These only need to be done once because these are fixed calculations.

    I also noticed that you did not have Sunday in your list of days… but since you are looking the days up by the index number this should be fine. Just wanted to point that out in case it was overlooked.

    I added a bunch of debug elements to show the output of the different variables. Honestly I’m not totally sure what your issue is, the code seems to work. If I switch out the delay on the setTimeout for something like 5 seconds, the countdown updates. So that part of it seems to be working. I hope maybe some of the output/debug elements can help you track it down.

    // Stream slots in UTC (Germany is UTC+2)
    const streamTimes = [
      //{ day: 0, hour: 0, minute: 0 },     // Sunday
      { day: 1, hour: 17, minute: 0 },     // Monday
      { day: 2, hour: 17, minute: 0 },     // Tuesday
      { day: 3, hour: 17, minute: 0 },     // Wednesday
      { day: 4, hour: 17, minute: 0 },     // Thursday
      { day: 5, hour: 18, minute: 0 },     // Friday
      { day: 6, hour: 13, minute: 0 },     // Saturday
    ];
    
    //Fixed time calculations
    const oneSecondMs = 1000
    const oneMinuteMs = oneSecondMs * 60;
    const oneHourMs = oneMinuteMs * 60;
    const oneDayMs = oneHourMs * 24;
    
    function getNextStreamTime() {
      const now = new Date();
      const currentDay = now.getUTCDay();
      const currentHour = now.getUTCHours();
      const currentMinute = now.getUTCMinutes();
      
      for (let i = 0; i < streamTimes.length; i++) {
        const streamTime = streamTimes[i];
        if (streamTime.day > currentDay || (streamTime.day === currentDay && streamTime.hour > currentHour) || (streamTime.day === currentDay && streamTime.hour === currentHour && streamTime.minute > currentMinute)) {
          return streamTime;
        }
      }
    
      // If there are no more stream slots, move on to monday
      return streamTimes[0];
    }
    
    function getCountdownString(timeDifference){
      const days = Math.floor(timeDifference / oneDayMs);
      const hours = Math.floor((timeDifference % oneDayMs) / oneHourMs);
      const minutes = Math.floor((timeDifference % oneHourMs) / oneMinuteMs);
      const seconds = Math.floor((timeDifference % oneMinuteMs) / oneSecondMs);
        
      return `${days} days, ${hours} hours, ${minutes} minutes, ${seconds} seconds`;
    }
    
    function startCountdown() {
      const countdownElement = document.getElementById("countdown");
      
      const nextStreamTime = getNextStreamTime();
      const targetDate = new Date();
      targetDate.setUTCHours(nextStreamTime.hour, nextStreamTime.minute, 0, 0);
      
      document.getElementById("debugNextStreamTime").innerHTML = JSON.stringify(nextStreamTime, null, 2);
      document.getElementById("debugTargetDate").innerHTML = targetDate;
      
      const timer = setInterval(() => {
        const currentDate = new Date();
        const timeDifference = targetDate - currentDate;
        
        document.getElementById("debugCountdown").innerHTML = getCountdownString(timeDifference);
        
        if (timeDifference <= 0) {
          clearInterval(timer);
          countdownElement.innerHTML = "Currently streaming";
          setTimeout(startCountdown, oneHourMs*2); 
        } else {
          countdownElement.innerHTML = getCountdownString(timeDifference);
        }
      }, oneSecondMs);
    }
    
    startCountdown();
    pre {background:#eee; border:1px solid #ccc; padding:5px; margin:5px 0;}
    <h4>Output: <span id="countdown"></span></h4>
    
    Next Stream Time
    <pre id="debugNextStreamTime"></pre>
    
    Target Date
    <pre id="debugTargetDate"></pre>
    
    Countdown
    <pre id="debugCountdown"></pre>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search