JavaScript中如何获取两个日期之间的差异?

123

我正在创建一个能够定义事件时间范围的应用程序。我希望当用户选择或更改开始日期时,自动填充结束日期。然而,我还不太清楚如何获取两个时间之间的差异,并使用该差异创建一个新的结束日期。


如何计算两个日期之间的天数? - starball
18个回答

81
在JavaScript中,可以通过调用getTime()方法将日期用于数值表达式来将日期转换为自纪元以来的毫秒数。 因此,要获取差异,只需减去两个日期。 要根据差异创建新日期,只需在构造函数中传递毫秒数。
var oldBegin = ...
var oldEnd = ...
var newBegin = ...

var newEnd = new Date(newBegin + oldEnd - oldBegin);

这应该只是有效的。

编辑: 修复了@bdukes指出的错误。

编辑:

关于行为的说明,oldBeginoldEndnewBegin都是Date实例。调用运算符+-将触发JavaScript自动转换并自动调用这些对象的valueOf()原型方法。恰巧,在Date对象中实现了valueOf()方法作为对getTime()的调用。

所以基本上:date.getTime() === date.valueOf() === (0 + date) === (+date)


需要什么格式才能让.getTime()正常工作呢?例如,new Date('22-12-2012 00:00').getTime()是无法正常工作的。有什么想法吗? - Jimmyt1988
1
对于在JS中进行日期解析,我建议你看一下这个问题:https://dev59.com/lXI-5IYBdhLWcg3w-96b - Vincent Robert
9
OldBegin、oldEnd 和 NewBegin 应该是“日期”对象吗?由于变量声明在此处被省略,很难确定它们应该是什么类型的对象。 - Anderson Green
此外,在JavaScript中,您可以使用一个函数来添加或减去日期:https://dev59.com/N3M_5IYBdhLWcg3w2XLw#1214753 - Anderson Green
小心添加数字和日期,详细解释请看下面我的答案。 - Dan

27

JavaScript天然支持日期差异的计算。

https://jsfiddle.net/b9chris/v5twbe3h/

var msMinute = 60*1000, 
    msDay = 60*60*24*1000,
    a = new Date(2012, 2, 12, 23, 59, 59),
    b = new Date("2013 march 12");


console.log(Math.floor((b - a) / msDay) + ' full days between'); // 364
console.log(Math.floor(((b - a) % msDay) / msMinute) + ' full minutes between'); // 0

现在来说一些容易犯的错误。试试这个:

console.log(a - 10); // 1331614798990
console.log(a + 10); // mixed string

因此,如果您要对一个数字和日期进行加法操作,将日期直接转换为number

console.log(a.getTime() - 10); // 1331614798990
console.log(a.getTime() + 10); // 1331614799010

我的第一个例子展示了Date对象的威力,但它实际上看起来像是一颗定时炸弹。


Dan,我发现你的示例最容易理解和跟进。谢谢。 - Melanie
5
“陷阱”实际上是基于语言规范的默认设置。减法运算符“-”会将参数强制转换为数字,因此Date对象返回它的时间值。加法运算符“+”是重载的,所以可能进行加法运算、数字强制转换或字符串连接操作。在这种情况下,由于Date对象被强制转换为字符串类型,因此“+”执行字符串连接操作。混淆并不是Date对象的错误,而是运算符重载造成的。 - RobG
我在编辑中添加了一个jsfiddle和上述代码的结果。我还提供了一种快速到达NaN的方法:b + 60000 - a。 - Chris Moschini
对于那些从搜索引擎过来的人,请避免将字符串传递给 new Date,除非是特定格式(请参见 JavaScript 中有效的日期时间字符串是什么?)。 - Heretic Monkey

11

查看 JsFiddle 演示

    var date1 = new Date();    
    var date2 = new Date("2025/07/30 21:59:00");
    //Customise date2 for your required future time

    showDiff();

function showDiff(date1, date2){

    var diff = (date2 - date1)/1000;
    diff = Math.abs(Math.floor(diff));

    var days = Math.floor(diff/(24*60*60));
    var leftSec = diff - days * 24*60*60;

    var hrs = Math.floor(leftSec/(60*60));
    var leftSec = leftSec - hrs * 60*60;

    var min = Math.floor(leftSec/(60));
    var leftSec = leftSec - min * 60;

    document.getElementById("showTime").innerHTML = "You have " + days + " days " + hrs + " hours " + min + " minutes and " + leftSec + " seconds before death.";

setTimeout(showDiff,1000);
}

对于你的HTML代码:

<div id="showTime"></div>

并非所有的日子在观察夏令时的地方都是24小时长。使用内置解析器来解析不支持的字符串格式并不是创建日期的好方法。 - RobG
对于那些来自搜索引擎的人,除非在特定格式下(参见JavaScript中有效的日期时间字符串是什么?),避免将字符串解析为new Date - Heretic Monkey

5

如果您不关心时间部分,可以使用.getDate().setDate()仅设置日期部分。

因此,要将结束日期设置为开始日期后的2周,可以执行以下操作:

function GetEndDate(startDate)
{
    var endDate = new Date(startDate.getTime());
    endDate.setDate(endDate.getDate()+14);
    return endDate;
}

要返回两个日期之间的差异(以天为单位),请执行以下操作:

function GetDateDiff(startDate, endDate)
{
    return endDate.getDate() - startDate.getDate();
}

最后,让我们修改第一个函数,使其可以将第二个函数返回的值作为参数传递:
function GetEndDate(startDate, days)
{
    var endDate = new Date(startDate.getTime());
    endDate.setDate(endDate.getDate() + days);
    return endDate;
}

33
GetDateDiff() 会跨越月份边界。例如,2011/04/26 和 2011/05/01 将返回 -25,但偏差应为 5 天。 - nfm
var ds = new Date(2014, 0, 31, 0, 0, 0, 0); var de = new Date(2014, 2, 31, 0, 0, 0, 0); GetDateDiff(ds,de) 返回 0。 - Noor

4

感谢@Vincent Robert,我最终使用了你的基本示例,不过实际上是newBegin + oldEnd - oldBegin。这是简化后的最终解决方案:

    // don't update end date if there's already an end date but not an old start date
    if (!oldEnd || oldBegin) {
        var selectedDateSpan = 1800000; // 30 minutes
        if (oldEnd) {
            selectedDateSpan = oldEnd - oldBegin;
        }

       newEnd = new Date(newBegin.getTime() + selectedDateSpan));
    }

1
解释为什么有时候你会使用 getTime,有时候又不用,这是一个很好的观点。 - Dan

3

根据您的需求,此函数将计算2天之间的差异,并以天为单位返回结果。

// This one returns a signed decimal. The sign indicates past or future.

this.getDateDiff = function(date1, date2) {
    return (date1.getTime() - date2.getTime()) / (1000 * 60 * 60 * 24);
}

// This one always returns a positive decimal. (Suggested by Koen below)

this.getDateDiff = function(date1, date2) {
    return Math.abs((date1.getTime() - date2.getTime()) / (1000 * 60 * 60 * 24));
}

1
将其放置在 Math.abs() 调用中,您将始终获得一个正的十进制数。 - Koen.
1
很好的建议Koen。这给了人们两个选择:像你建议的那样只是真实的日期差异,或者带有符号的日期差异,表示差异是在过去还是未来。 :) - sparkyspider
请注意,在JavaScript中,您还可以在毫秒级别上添加/减去数字以获取未来/过去的时间。var nextMinute = new Date( someDate.getTime() + 60 * 1000 ); - Dan
这是一个打字错误吗?“between the 2 days”。可能是指两个日期之间。 - tomazahlin

2
如果使用moment.js,有一个更简单的解决方案,可以在一行代码中给出天数差异。
moment(endDate).diff(moment(beginDate), 'days');

更多详细信息请参见moment.js页面

祝好, 米格尔


1
以下代码将返回从今天到未来日期的剩余天数。
依赖项:jQuery和MomentJs。
var getDaysLeft = function (date) {
  var today = new Date();
  var daysLeftInMilliSec = Math.abs(new Date(moment(today).format('YYYY-MM-DD')) - new Date(date));
  var daysLeft = daysLeftInMilliSec / (1000 * 60 * 60 * 24);   
  return daysLeft;
};

getDaysLeft('YYYY-MM-DD');

1
function compare()
{
  var end_actual_time    = $('#date3').val();

  start_actual_time = new Date();
  end_actual_time = new Date(end_actual_time);

  var diff = end_actual_time-start_actual_time;

  var diffSeconds = diff/1000;
  var HH = Math.floor(diffSeconds/3600);
  var MM = Math.floor(diffSeconds%3600)/60;

  var formatted = ((HH < 10)?("0" + HH):HH) + ":" + ((MM < 10)?("0" + MM):MM)
  getTime(diffSeconds);
}
function getTime(seconds) {
  var days = Math.floor(leftover / 86400);

  //how many seconds are left
  leftover = leftover - (days * 86400);

  //how many full hours fits in the amount of leftover seconds
  var hours = Math.floor(leftover / 3600);

  //how many seconds are left
  leftover = leftover - (hours * 3600);

  //how many minutes fits in the amount of leftover seconds
  var minutes = leftover / 60;

  //how many seconds are left
  //leftover = leftover - (minutes * 60);
  alert(days + ':' + hours + ':' + minutes);
}

1

替代修改扩展代码...

http://jsfiddle.net/vvGPQ/48/

showDiff();

function showDiff(){
var date1 = new Date("2013/01/18 06:59:00");   
var date2 = new Date();
//Customise date2 for your required future time

var diff = (date2 - date1)/1000;
var diff = Math.abs(Math.floor(diff));

var years = Math.floor(diff/(365*24*60*60));
var leftSec = diff - years * 365*24*60*60;

var month = Math.floor(leftSec/((365/12)*24*60*60));
var leftSec = leftSec - month * (365/12)*24*60*60;    

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

var hrs = Math.floor(leftSec/(60*60));
var leftSec = leftSec - hrs * 60*60;

var min = Math.floor(leftSec/(60));
var leftSec = leftSec - min * 60;




document.getElementById("showTime").innerHTML = "You have " + years + " years "+ month + " month " + days + " days " + hrs + " hours " + min + " minutes and " + leftSec + " seconds the life time has passed.";

setTimeout(showDiff,1000);
}

请进一步澄清你的回答并使用更好的英语。 - anon
这个解决方案是错误的,因为你使用了365天,忽略了闰年。 - Serhii Holinei
对于那些从搜索引擎过来的人,请避免将字符串传递给 new Date,除非是特定格式(请参见 JavaScript 中有效的日期时间字符串是什么?)。 - Heretic Monkey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接