【问题标题】:javascript run a function every quarter hour at 00, 15, 30 ,45javascript 每一刻钟在 00、15、30、45 运行一个函数
【发布时间】:2013-03-21 14:25:02
【问题描述】:

我有以下代码取自堆栈溢出:

   function doSomething() {
       var d = new Date(),
       h = new Date(d.getFullYear(), d.getMonth(), d.getDate(), d.getHours() + 1, 0, 0, 0),
       e = h - d;
       window.setTimeout(doSomething, e);

       //code to be run
       alert("On the hour")
    }
    doSomething(); 

这非常有效,并且每小时都会产生一个警报。 我希望函数在 00、15、30 和 45 点每 15 分钟运行一次

【问题讨论】:

    标签: javascript settimeout


    【解决方案1】:

    获取下一个偶数15分钟的时间:

    (d.getMinutes() - (d.getMinutes() % 15)) + 15
    

    例如,当您在 13:43 调用 doSomething() 时,它将在下次 13:45 运行:

    ( 43 - (43 % 15) + 15 ) = ( 43 - 13 + 15 ) = 45
    

    那么它就会按预期运行:14:00、14:15等等……

    完整代码:

    function doSomething() {
         var d = new Date(),
             h = new Date(d.getFullYear(), d.getMonth(), d.getDate(), d.getHours(), (d.getMinutes() - (d.getMinutes() % 15)) + 15, 0, 0),
             e = h - d;
         window.setTimeout(doSomething, e);
    
         console.log('run');
     }
     doSomething();
    

    【讨论】:

    • 如果它在 46 分钟内你会遇到问题......没有?
    • @IdanHen - 我添加了一个部分来解释这背后的数学;)
    • @IdanHen new Date() 会在你传递大于 59 的分钟值时处理它
    • @awbergs - 是的。我总是尝试使用 OP 的代码来回答。我认为它(通常)效果最好,因为 OP 可以看到他的尝试和解决方案之间的区别 - 这有助于学习。
    • @awbergs 你的解决方案是什么?我有兴趣看看。刚看到
    【解决方案2】:

    这比其他人提出的要复杂一些。你不想要从现在开始的 15 分钟,你想要 15 分钟,从下一个最近的开始。有很多方法可以做到这一点,但我首先想到的是这个:

    function doSomething() {
       var d = new Date();
       var minutes = 15 - d.getMinutes() % 15; // the number of minutes till the next 15.
       window.setTimeout(doSomething, minutes * 60 * 1000);
    
       //code to be run
       alert("On the quarter-hour")
    }
    doSomething(); 
    

    试一试。 :-)

    编辑

    上面的代码是最简单的,但会出现问题,因为它只查看分钟。它最多可以漂移 59.999 秒,并且根据处理器负载,甚至可能偶尔出现在 1、16、31 或 46 上。为确保不会发生这种情况,您需要减去:

    function doSomething() {
       var d = new Date();
       var minutes = 15 - d.getMinutes() % 15; // the number of minutes till the next 15.
       var h = new Date(d.getYear(), d.getMonth(), d.getDay(), d.getHours(), d.getMinutes() + minutes, 0);
       var e = h-d;
       window.setTimeout(doSomething, e);
    
       //code to be run
       alert("On the quarter-hour")
    }
    doSomething(); 
    

    这可以让你精确到秒,而我原来的帖子只精确到分钟。

    【讨论】:

    • 不错 - 但是您的警报/警报会迟到一分钟,因为您只是在数分钟。即在 09:14:59 - 你将在一分钟内让闹钟响起。
    • 嗯...最多延迟 59.999 秒。 :-) 认为处理器足够快,我们可以始终保持在正确的时间。不过,我想我应该考虑到这一点。
    【解决方案3】:

    看看函数在做什么。您有一个变量 h 设置为当前时间后一小时。

    //Gets the current date
    var d = new Date() 
    
    //Note the +1
    h = new Date(d.getFullYear(), d.getMonth(), d.getDate(), d.getHours() + 1, 0, 0, 0)
    

    Date构造函数中的每个参数对应一个时间间隔

    new Date(year, month, day, hours, minutes, milliseconds)
    

    使用这一新发现的知识,我们可以推断,我们需要在当前时间上增加 15 分钟,而不是在当前时间上加一。问题是我们不能只是盲目地添加 15 分钟并认为我们已经准备好了,因为我们真正想要的是开始以四分之一小时为间隔并执行下一刻钟再次。

    为了解决这个难题,我们必须找出距离下一个季度间隔有多远,并将其设置为我们的超时值。

    var d = new Date();
    
    var currentSeconds = d.getMinutes() * 60 + d.getSeconds();
    
    var secondsFromQuarter = 900 - currentSeconds % 900;
    

    现在我们知道调用doSomething 需要等待多少秒,但我们必须将其转换为毫秒。

    var millisecondsFromQuarter = minutesFromQuarter * 1000;
    

    瞧!从这里我们可以像上面一样使用 millisecondsFromQuarter 值调用 setTimeout:

    window.setTimeout(doSomething, millisecondsFromQuarter);
    

    免责声明

    这将精确到秒。如果需要精确到毫秒,那么您只需像这样比较毫秒值:

    var currentMilliseconds = d.getMinutes() * 60 * 1000 + d.getSeconds() * 1000 + d.getMilliseconds();
    
    var MillisecondsFromQuarter = 900000 - currentSeconds % 900000;
    

    免责声明 #2

    我对@kamituel 的回答投了赞成票,因为它在视觉上以更清晰的方式有效地完成了同样的事情。我不确定哪个对性能更好,但可能是 6:6

    【讨论】:

      【解决方案4】:
       function doSomething() {
         var d = new Date(),
         current_minutes = d.getMinutes(),
         current_hour = d.getHours(),
         next_min_hit = 0;
      
         if ( current_minutes >= 0 && current_minutes < 15 )
            next_min_hit = 15;
         if ( current_minutes >= 15 && current_minutes < 30 )
            next_min_hit = 30;
         if ( current_minutes >= 30 && current_minutes < 45 )
            next_min_hit = 45;
         if ( current_minutes >= 45 && current_minutes < 59 ){
            next_min_hit = 0;
            current_hour++;
         }
         var h = new Date(d.getFullYear(), d.getMonth(), d.getDate(), current_hour, next_min_hit , 0, 0),
         e = h - d;
         window.setTimeout(doSomething, e);
      
         //code to be run
         alert("On the hour")
      }
      doSomething(); 
      

      【讨论】:

      • 如果我12:22开门,会在12:37运行
      • 哦,我从第二次跑步中想到,你希望每 15 分钟一次。
      • 现在这应该可以工作了,如果最小 45 或更高,日期设置为小时 +1。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-05
      • 2020-09-25
      • 1970-01-01
      • 2012-08-28
      • 1970-01-01
      • 2018-08-08
      相关资源
      最近更新 更多