【问题标题】:Best Way to detect midnight and reset data检测午夜和重置数据的最佳方法
【发布时间】:2014-10-15 16:04:24
【问题描述】:

我一直在开发一个 Web 应用程序仪表板,我想知道如何检测是午夜,以便使用 jquery 或 momentjs 重置一些包含前一天数据的数组。

【问题讨论】:

  • 你说的是服务器还是客户端?我不确定你想在客户端上这样做......
  • 我说的是客户端。我唯一不想要的是刷新页面。例如,我想要的是:想象你有一个包含数据的数组,我想重置这个数组。如果是午夜,我也不想每 5 秒检查一次(如果可能)
  • 好的,你如何定义午夜?这是0:00 小时吗?
  • 午夜为 0,但检测午夜有问题。最好的做法是重新考虑您的应用程序目标,然后继续完成任务。 if(is_midnight())午夜返回 0,所以逻辑上它是错误的
  • @JuanJardim 我添加了我的答案。尝试更改midnight 变量并查看结果。

标签: javascript jquery momentjs


【解决方案1】:

使用moment().format("h:mm:ss")h:mm:ss 格式返回时间。

var midnight = "0:00:00";
var now = null;

setInterval(function () {
    now = moment().format("H:mm:ss");
    if (now === midnight) {
        alert("Hi");
    }
    $("#time").text(now);
}, 1000);

JSFIDDLE

更好的方法是计算直到午夜的秒数。这使用 MomentJS 非常简单且易于阅读:

// returns the number of seconds until next midnight
moment("24:00:00", "hh:mm:ss").diff(moment(), 'seconds');

所以,做吧:

setTimeout(
   midnightTask,
   moment("24:00:00", "hh:mm:ss").diff(moment(), 'seconds')
);

function midnightTask() {
  /* do something */
}

JSFIDDLE

【讨论】:

  • 第二个解决方案 (setTimeout) 如果计算机进入睡眠状态并在很久以后恢复,则将不起作用。在这种情况下,触发器的延迟时间与计算机处于睡眠模式的时间差不多。
  • "h" 为您提供 12 小时格式,因此 moment().format("h:mm:ss") 将在午夜为“12:00:00”。检查“HH:mm:ss”与“00:00:00”应该可以工作。
  • @Dunc 哎呀!非常感谢! :D
【解决方案2】:

实际上只有两种方法可以做到这一点

  1. 每 x 秒轮询一次,看看我们是否在午夜后 x 秒内
  2. 计算从现在到午夜的时间,并在执行前休眠这段时间

(1) 已在其他答案中得到证明,这里是 (2)。

首先要做的是calculate the number of milliseconds until midnight,然后将其用作javascripts setTimeout的参数。

setTimeout(function(){
  // whatever you want to do at midnight
}, msToMidnight);

在完成该函数的工作后,您可能需要重新计算直到下一个午夜的时间并重复该过程。

【讨论】:

    【解决方案3】:

    所以我认为你的做法是错误的。您要查找的不是午夜时分,您只想知道这一天何时发生变化,这是一项简单得多的任务。

    我要说的第一件事是不惜一切代价避免使用计时器。他们不值得。每天运行 > 3600 次相同的功能所花费的性能损失和额外的 CPU 时间是荒谬的,尤其是当它在其他人的计算机上运行时。你不知道它可以处理多少,所以假设它根本无法处理。让您的用户轻松一点。

    我建议收听用户输入事件,假设这是您在普通计算机上拥有的东西,而不是something like this,没有用户输入。

    如果您可以依赖用户输入事件,我会这样做..

    var today = new Date(), lastUpdate;
    
    window.addEventListener( "mousemove", function () {
      var time = new Date();
      // If we haven't checked yet, or if it's been more than 30 seconds since the last check
      if ( !lastUpdate || ( time.getTime() - lastUpdate.getTime() ) > 30000 ) {
        // Set the last time we checked, and then check if the date has changed.
        lastUpdate = time
        if ( time.getDate() !== today.getDate() ) {
          // If the date has changed, set the date to the new date, and refresh stuff.
          today = time
    
          this_is_where_you_would_reset_stuff()
        }
      }
    } )
    

    如果您绝对需要使用计时器,那么我会这样做..

    function init() {
      var today = new Date();
      var midnight = new Date();
    
      midnight.setDate( today.getDate() + 1 )
      midnight.setHours( 0 )
      midnight.setMinutes( 0 )
    
      setTimeout( function () {
        // If the date has changed, set the date to the new date, and refresh stuff.
        today = time
    
        this_is_where_you_would_reset_stuff()
    
        init()
      }, midnight.getTime() - today.getTime() )
    }
    
    init()
    

    请记住,第二种方法的可靠性可能要低得多。

    【讨论】:

    • 这种方法的问题在于,这个仪表板要显示在监视器中,用户只能看到数据的变化。不过谢谢你的建议
    • 每次鼠标移动时都会查询系统计时器。这是你想做的最后一件事。即使是创建 Date 对象本身也比您想做的更多,因为鼠标移动了。
    【解决方案4】:

    在今天早上的午夜创建一个日期,加上 86400 秒,然后设置一个超时时间:

    new Date(Date.parse((new Date()).toString().replace(/\d\d:\d\d:\d\d/,'00:00:00')) + 86400 * 1000)
    

    以下是您的使用方法:

    var delay_to_midnight = Date.parse((new Date()).toString().replace(/\d\d:\d\d:\d\d/,'00:00:00')) + 86400 * 1000 - Date.now()
    var timeoutid = window.setTimeout(function() { alert("It's midnight!"); }, delay_to_midnight);
    

    【讨论】:

      【解决方案5】:

      我会尝试:

      window.setInterval(resetAtMidnight, 1000*5) // every five seconds
      function resetAtMidnight() {
        var now = new Date();
        if(now.getHours() < 1
         && now.getMinutes() < 1
         && now.getSeconds() < 5 ) {
          redrawPage();
        }
      };
      

      【讨论】:

      • 为什么还要让 CPU 工作得比它需要的还要努力。 1000*5 = 5000,为什么不直接传入5000
      • 会在 5 秒延迟后重复,还是只运行一次函数?
      • @gibberish - 这只会运行一次,重复你使用setInterval(或再次调用setTimeout
      • @self 我将它拼写为1000*5,因为它更容易看到发生了什么,尤其是在像1000*60*60*4(4 小时)这样的长间隔内。此外,它只需要计算一次,而不是每个间隔
      • 请不要这样做。
      猜你喜欢
      • 2013-08-25
      • 2011-04-23
      • 1970-01-01
      • 2020-09-30
      • 1970-01-01
      • 2013-09-28
      • 2013-06-09
      • 2011-02-17
      相关资源
      最近更新 更多