在JS中使用.date()来计算两个日期之间的差异,我做错了什么?

时间:2011-01-28 13:58:03

标签: javascript date time

下午,

我正在使用JS计算两个日期之间的差异。我试图将结果精确到一秒钟。我一直很好,但注意到了一个问题。下面显示的前两个日期显示了5年的差异,但是一旦我在未来的日期再添加一年,它会显示5年,1天。额外的一天从哪里来?当未来日期到达2020年时,它会在结果中再添加一天,这是一种反复出现的模式。有人可以开导我吗?我还没有涉及任何闰年计算,我已将我的代码放在下面:

$(document).ready(function(){

    var todaysDate = new Date('2010/11/24 23:00:00');   
    var futureDate = new Date('2020/11/24 22:59:00');

    calculateTime(todaysDate,futureDate);
});

function calculateTime(todaysDate,futureDate){  
    var difference = futureDate.getTime() - todaysDate.getTime(); 

    var years = Math.floor(difference/1000/60/60/24/365);
        difference -= years*1000*60*60*24*365;

    var days = Math.floor(difference/1000/60/60/24);
        difference -= days*1000*60*60*24;

    var hours = Math.floor(difference/1000/60/60);
        difference -= hours*1000*60*60;

    var minutes = Math.floor(difference/1000/60);
        difference -= minutes*60*1000;

    var seconds = Math.floor(difference/1000);

    var result = years + ' Years, ';
        result += days + ' Days, ';
        result += hours + ' Hours, ';
        result += minutes + ' Minutes, ';
        result += seconds + ' Seconds';

    $('#time').html(result)
 }

3 个答案:

答案 0 :(得分:4)

是的,2020年是闰年,所以如果您的初步测试是2010-2019,那么您尝试2010-2020,由于闰年还有一天。即使您没有明确处理闰年,Javascript日期对象也是闰年,因此差异将包括额外的一天的秒数。

尝试区别对待

1) 2010/11/24 -> 2020/02/28
2) 2010/11/24 -> 2020/03/01

你最终应该有86,400,000的差异。

答案 1 :(得分:0)

是的,问题出在闰年。你的行

var years = Math.floor(difference/1000/60/60/24/365);

不计算两个日期之间的年数差异,而是计算它们之间的365天期间的数量

答案 2 :(得分:0)

最大的错误是没有编写测试套件:

  1. 检查您在开发时知道的边缘情况
  2. 稍后您可以轻松查看其他边缘情况
  3. 可测试代码通常更模块化(请参阅下面的mock object我必须创建以解决函数与jQuery的强连接:如果jQuery调用已经超出{{1}那么会更容易})
  4. 这称为 test-driven development

    现在我发现了其他一些错误:

    1. 您的日期字符串格式不尊重the specification。您的系统了解您的格式,但有些可能不会。
    2. 您的日期字符串未指定时区,因此您将在区域设置上遇到夏令时问题。
    3. 您的功能会为您提供有效的经过时间,但这可能不是您的用户感兴趣的内容。特别是在涉及夏令时时:您可能需要+ 1 / -1小时。
    4. 这是一个可以在Windows命令行提示符下运行的测试套件(使用calculateTime来运行它):

      cscript testsuite.js

      以下是我的输出(当地时区(法国)偏移在2010-10-31和2011-03-26更改):

      // jQuery mock object for calculateTime testing
      // $('#time').html(result) => result is stored in $.result
      var $ = (function() {
          var $, $$ = {
              html: function(result) {
                  $.result = result
              }
          }
          return $ = function(ignore) {
              return $$
          }
      })();
      
      // Henryz's unmodified function
      function calculateTime(todaysDate,futureDate) {
          var difference = futureDate.getTime() - todaysDate.getTime(); 
      
          var years = Math.floor(difference/1000/60/60/24/365);
              difference -= years*1000*60*60*24*365;
      
          var days = Math.floor(difference/1000/60/60/24);
              difference -= days*1000*60*60*24;
      
          var hours = Math.floor(difference/1000/60/60);
              difference -= hours*1000*60*60;
      
          var minutes = Math.floor(difference/1000/60);
              difference -= minutes*60*1000;
      
          var seconds = Math.floor(difference/1000);
      
          var result = years + ' Years, ';
              result += days + ' Days, ';
              result += hours + ' Hours, ';
              result += minutes + ' Minutes, ';
              result += seconds + ' Seconds';
      
          return $('#time').html(result)
      }
      
      function test(a, b, expected) {
          var toString = Object.prototype.toString;
          if (toString.apply(a) != '[object Date]') a = new Date(a);
          if (toString.apply(b) != '[object Date]') b = new Date(b);
          calculateTime(a, b);
          var got = $.result;
          WScript.Echo(
              got === expected
              ? "ok"
              : "not ok - ["+a.toString()+"] to ["+b.toString()+"]\r\n#      Got: "+got+"\r\n# Expected: "+expected
          );
      }
      
      test('2010/11/24 23:00:00', '2011/11/24 23:00:00', '1 Years, 0 Days, 0 Hours, 0 Minutes, 0 Seconds');
      test('Nov 24, 2010 23:00:00', 'Nov 24, 2011 23:00:00', '1 Years, 0 Days, 0 Hours, 0 Minutes, 0 Seconds');
      test('2010/11/24 23:00:00', '2020/11/24 22:59:00', '10 Years, 0 Days, 0 Hours, 0 Minutes, 0 Seconds');
      test('2011/03/26 23:00:00', '2011/03/27 23:00:00', '0 Years, 1 Days, 0 Hours, 0 Minutes, 0 Seconds');
      test('2010/10/30 23:00:00', '2010/10/31 23:00:00', '0 Years, 1 Days, 0 Hours, 0 Minutes, 0 Seconds');
      

      所以你应该完全重写函数或者更好,使用现有的,经过测试的实现。