为什么连接到我用JavaScript编写的倒计时器后,消息在两小时后没有消失?

huangapple go评论55阅读模式
英文:

Why is the message not disappearing after two hours when connected to my countdown timer written in JavaScript?

问题

"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.

英文:

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 &lt; streamTimes.length; i++) {
const streamTime = streamTimes[i];
if (streamTime.day &gt; currentDay || (streamTime.day === currentDay &amp;&amp; streamTime.hour &gt; currentHour) || (streamTime.day === currentDay &amp;&amp; streamTime.hour === currentHour &amp;&amp; streamTime.minute &gt; currentMinute)) {
return streamTime;
}
}
// If there are no more stream slots, move on to monday
return streamTimes[0];
}
function startCountdown() {
const countdownElement = document.getElementById(&quot;countdown&quot;);
const nextStreamTime = getNextStreamTime();
const targetDate = new Date();
targetDate.setUTCHours(nextStreamTime.hour, nextStreamTime.minute, 0, 0);
const timer = setInterval(() =&gt; {
const currentDate = new Date();
const timeDifference = targetDate - currentDate;
if (timeDifference &lt;= 0) {
clearInterval(timer);
countdownElement.innerHTML = &quot;Currently streaming&quot;;
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.

答案1

得分: 1

所以在 day=1 时,你在 19:00 结束了流程,然后你将目标日期设置为同一天,但时间是 17:00。这意味着 targetDate - currentDate 将小于 0,因为你还没有将 targetDate 设置为第二天,所以它会显示 Currently streaming 并设置另一个定时器为 2 小时。直到第二天,它才会真正开始工作。替换:

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

864E5 是一天的毫秒数,所以如果目标日期是明天,你想要将它添加到当前日期中。

英文:

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

答案2

得分: 0

我复制了你的代码并做了一些更改。首先,有一堆数字计算,表示持续时间,这些计算多次重复,然后每秒重新计算一次。这些只需要计算一次,因为它们是固定的计算。

我还注意到你的星期天没有在星期列表中...但由于你是通过索引号查找星期的,这应该没问题。只是想提醒一下,以防被忽略了。

我添加了一些调试元素,以显示不同变量的输出。老实说,我不太确定你的问题是什么,代码似乎是有效的。如果我将setTimeout的延迟更改为比如5秒,倒计时会更新。所以这部分似乎是有效的。我希望输出/调试元素中的一些内容可以帮助你追踪问题。

// 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>
英文:

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.

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

// 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 &lt; streamTimes.length; i++) {
const streamTime = streamTimes[i];
if (streamTime.day &gt; currentDay || (streamTime.day === currentDay &amp;&amp; streamTime.hour &gt; currentHour) || (streamTime.day === currentDay &amp;&amp; streamTime.hour === currentHour &amp;&amp; streamTime.minute &gt; 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(&quot;countdown&quot;);
const nextStreamTime = getNextStreamTime();
const targetDate = new Date();
targetDate.setUTCHours(nextStreamTime.hour, nextStreamTime.minute, 0, 0);
document.getElementById(&quot;debugNextStreamTime&quot;).innerHTML = JSON.stringify(nextStreamTime, null, 2);
document.getElementById(&quot;debugTargetDate&quot;).innerHTML = targetDate;
const timer = setInterval(() =&gt; {
const currentDate = new Date();
const timeDifference = targetDate - currentDate;
document.getElementById(&quot;debugCountdown&quot;).innerHTML = getCountdownString(timeDifference);
if (timeDifference &lt;= 0) {
clearInterval(timer);
countdownElement.innerHTML = &quot;Currently streaming&quot;;
setTimeout(startCountdown, oneHourMs*2); 
} else {
countdownElement.innerHTML = getCountdownString(timeDifference);
}
}, oneSecondMs);
}
startCountdown();

<!-- language: lang-css -->

pre {background:#eee; border:1px solid #ccc; padding:5px; margin:5px 0;}

<!-- language: lang-html -->

&lt;h4&gt;Output: &lt;span id=&quot;countdown&quot;&gt;&lt;/span&gt;&lt;/h4&gt;
Next Stream Time
&lt;pre id=&quot;debugNextStreamTime&quot;&gt;&lt;/pre&gt;
Target Date
&lt;pre id=&quot;debugTargetDate&quot;&gt;&lt;/pre&gt;
Countdown
&lt;pre id=&quot;debugCountdown&quot;&gt;&lt;/pre&gt;

<!-- end snippet -->

huangapple
  • 本文由 发表于 2023年5月25日 03:55:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/76326996.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定