如何计算JavaScript中的日期差?


181

我想以天,小时,分钟,秒,毫秒,纳秒为单位计算日期差。我该怎么做?



1
如果涉及的两个日期位于不同的时区,则下面的解决方案将失效。请参阅的问题,以获得更准确的解决方案stackoverflow.com/questions/3224834/…
Shyam Habarakada 2014年

Answers:


219

假设您有两个Date对象 s,您可以将它们相减以获得毫秒数之差:

var difference = date2 - date1;

从那里,您可以使用简单的算法来得出其他值。


38
这是正确的答案。例如:要获得天数差异Math.floor((date2 - date1) / (1000*60*60*24))-对于任何其他单位的差异,请调整分母(基本值以ms为单位)。
trisweb

32
没有将毫秒转换为年份的“简单”算法。您必须注意双性恋年份,时区,并且有些日子有23或25个小时。某些年份有365,25天,因此这里没有简单的算法(仍在寻找准确的解决方案)。
2014年

6
@亚历山大:这个问题多年来从未问过。确实,计算年度差异并非易事。但是,对于几天,这是正确的,假设日期在同一时区(一个不合理的假设)。据我所知,一天定义为24小时,而由于夏令时造成的任何“变化”实际上都是时区的切换。如果您还没有区分时区,那么试图找出时差将使您陷入痛苦的世界,这尤其是因为DST切换“重复”了时间。不过,只要停留在一个时区,一切都可以。
icktoofay,2014年

12
@trisweb-即使只是几天之内就变得简单,也比您的评论要复杂。在星期二晚上10点到星期三上午9点之间有多少天?你说的算法0其他人可能会认为1
RobG

@RobG相对论者甚至可能认为大于1或小于0。这完全取决于观察者。
无辜的旁观者

78
var DateDiff = {

    inDays: function(d1, d2) {
        var t2 = d2.getTime();
        var t1 = d1.getTime();

        return parseInt((t2-t1)/(24*3600*1000));
    },

    inWeeks: function(d1, d2) {
        var t2 = d2.getTime();
        var t1 = d1.getTime();

        return parseInt((t2-t1)/(24*3600*1000*7));
    },

    inMonths: function(d1, d2) {
        var d1Y = d1.getFullYear();
        var d2Y = d2.getFullYear();
        var d1M = d1.getMonth();
        var d2M = d2.getMonth();

        return (d2M+12*d2Y)-(d1M+12*d1Y);
    },

    inYears: function(d1, d2) {
        return d2.getFullYear()-d1.getFullYear();
    }
}

var dString = "May, 20, 1984";

var d1 = new Date(dString);
var d2 = new Date();

document.write("<br />Number of <b>days</b> since "+dString+": "+DateDiff.inDays(d1, d2));
document.write("<br />Number of <b>weeks</b> since "+dString+": "+DateDiff.inWeeks(d1, d2));
document.write("<br />Number of <b>months</b> since "+dString+": "+DateDiff.inMonths(d1, d2));
document.write("<br />Number of <b>years</b> since "+dString+": "+DateDiff.inYears(d1, d2));

此处获取的代码示例。


如果用作单个计数器,则仅以给定格式返回日期差。例如,如果您要3个月4天零5个小时,则不会产生这些结果。3个月96天零几个小时的时间更长。
Joris Kroos

30

另一种解决方案是将差分转换为新的Date对象,并获取该日期的年份(与1970年不同),月份,日期等。

var date1 = new Date(2010, 6, 17);
var date2 = new Date(2013, 12, 18);
var diff = new Date(date2.getTime() - date1.getTime());
// diff is: Thu Jul 05 1973 04:00:00 GMT+0300 (EEST)

console.log(diff.getUTCFullYear() - 1970); // Gives difference as year
// 3

console.log(diff.getUTCMonth()); // Gives month count of difference
// 6

console.log(diff.getUTCDate() - 1); // Gives day count of difference
// 4

所以区别就像“ 3年6个月零4天”。如果您想以一种人类可读的方式来与众不同,那么可以为您提供帮助。


不是这个意思!我们希望与众不同!在此示例中,天的差异数为1281,而不是4!
chaim.dev 2014年

3
@ chaim.dev“如果您想以一种人类可读的方式来有所作为,那可以为您提供帮助。”
穆拉特·乔鲁(MuratÇorlu),2015年

7
这是不可靠的。它没有考虑到不同的月份长度,leap年和其他异常情况。
马克·杜丁

2
感谢Murat,此解决方案已解决了我的问题。我真正想要的是它必须以与php相同的方式工作。
Ritesh Patadiya

27

诸如“天之差”之类的表达从未像看起来那样简单。如果您有以下日期:

d1: 2011-10-15 23:59:00
d1: 2011-10-16 00:01:00

时间差是2分钟,“天差”应该是1还是0?如果以月,年或其他任何形式表示差异,也会出现类似的问题,因为年,月和日的长度和时间是不同的(例如,夏时制开始的那一天比平时缩短了1个小时,而比夏令时缩短了2个小时)它结束)。

这是一个忽略天数的差异函数,即对于上述日期,它返回1。

/*
   Get the number of days between two dates - not inclusive.

   "between" does not include the start date, so days
   between Thursday and Friday is one, Thursday to Saturday
   is two, and so on. Between Friday and the following Friday is 7.

   e.g. getDaysBetweenDates( 22-Jul-2011, 29-jul-2011) => 7.

   If want inclusive dates (e.g. leave from 1/1/2011 to 30/1/2011),
   use date prior to start date (i.e. 31/12/2010 to 30/1/2011).

   Only calculates whole days.

   Assumes d0 <= d1
*/
function getDaysBetweenDates(d0, d1) {

  var msPerDay = 8.64e7;

  // Copy dates so don't mess them up
  var x0 = new Date(d0);
  var x1 = new Date(d1);

  // Set to noon - avoid DST errors
  x0.setHours(12,0,0);
  x1.setHours(12,0,0);

  // Round to remove daylight saving errors
  return Math.round( (x1 - x0) / msPerDay );
}

这可以更加简洁:

/*  Return number of days between d0 and d1.
**  Returns positive if d0 < d1, otherwise negative.
**
**  e.g. between 2000-02-28 and 2001-02-28 there are 366 days
**       between 2015-12-28 and 2015-12-29 there is 1 day
**       between 2015-12-28 23:59:59 and 2015-12-29 00:00:01 there is 1 day
**       between 2015-12-28 00:00:01 and 2015-12-28 23:59:59 there are 0 days
**        
**  @param {Date} d0  - start date
**  @param {Date} d1  - end date
**  @returns {number} - whole number of days between d0 and d1
**
*/
function daysDifference(d0, d1) {
  var diff = new Date(+d1).setHours(12) - new Date(+d0).setHours(12);
  return Math.round(diff/8.64e7);
}

// Simple formatter
function formatDate(date){
  return [date.getFullYear(),('0'+(date.getMonth()+1)).slice(-2),('0'+date.getDate()).slice(-2)].join('-');
}

// Examples
[[new Date(2000,1,28), new Date(2001,1,28)],  // Leap year
 [new Date(2001,1,28), new Date(2002,1,28)],  // Not leap year
 [new Date(2017,0,1),  new Date(2017,1,1)] 
].forEach(function(dates) {
  document.write('From ' + formatDate(dates[0]) + ' to ' + formatDate(dates[1]) +
                 ' is ' + daysDifference(dates[0],dates[1]) + ' days<br>');
});


1
@rudeovskiz​​ebear-在IE,Firefox和Safari中测试过,可以正常工作。它使用了我希望可以在任何浏览器中使用的基本ECMAScript,对您来说什么不起作用?
RobG

我将其放在测试页上,并且在chrome中可以正常工作,但在IE9和最新的FF中,我一直保持无效状态
mnsr 2013年

@RafiB。-我不知道您如何认为一个比另一个更准确,它们本质上是相同的,即使用UTC时间值计算整天的差异。这个问题的含糊不清。如果是这样,则可能导致不同的解决方案。
RobG

@RobG请在更简洁的解决方案的注释中编辑示例。该月应为“ 12”而不是“ 22”
S.aad

1
@IgorKudryashov-对不起,我只是不明白。2000年是a年,因此2000年2月28日到2001年2月28日是366天。在非-年,这是365天。我添加了更多示例。
RobG

18
<html lang="en">
<head>
<script>
function getDateDiff(time1, time2) {
  var str1= time1.split('/');
  var str2= time2.split('/');

  //                yyyy   , mm       , dd
  var t1 = new Date(str1[2], str1[0]-1, str1[1]);
  var t2 = new Date(str2[2], str2[0]-1, str2[1]);

  var diffMS = t1 - t2;    
  console.log(diffMS + ' ms');

  var diffS = diffMS / 1000;    
  console.log(diffS + ' ');

  var diffM = diffS / 60;
  console.log(diffM + ' minutes');

  var diffH = diffM / 60;
  console.log(diffH + ' hours');

  var diffD = diffH / 24;
  console.log(diffD + ' days');
  alert(diffD);
}

//alert(getDateDiff('10/18/2013','10/14/2013'));
</script>
</head>
<body>
  <input type="button" 
       onclick="getDateDiff('10/18/2013','10/14/2013')" 
       value="clickHere()" />

</body>
</html>

帮不了我 用相同的方法不能将其扩展到几个月或几年。
tomazahlin

9

使用Moment.js进行所有与JavaScript相关的日期时间计算

您的问题的答案是:

var a = moment([2007, 0, 29]);   
var b = moment([2007, 0, 28]);    
a.diff(b) // 86400000  

完整的细节可以在这里找到


4
拥抱额外的400+ Kb,仅差一点日期。
罗密欧·米哈尔恰

@RomeoMihalcea当前的最小化moment.js 2.22.2(具有一种语言环境)为53 KB,压缩后为17 KB。我了解您的担心。它是一个巨大的库,只能用于一个简单的函数,但是它可以处理许多与日期/时间相关的怪癖,因此通常很值得。
HeikoS

8
function DateDiff(date1, date2) {
    date1.setHours(0);
    date1.setMinutes(0, 0, 0);
    date2.setHours(0);
    date2.setMinutes(0, 0, 0);
    var datediff = Math.abs(date1.getTime() - date2.getTime()); // difference 
    return parseInt(datediff / (24 * 60 * 60 * 1000), 10); //Convert values days and return value      
}

感谢您的解决方案:)
bhagirathi

我发现的大多数解决方案都行不通或太耗时。到目前为止,您的解决方案是最简单的,并且可以按预期工作!干杯:)
布鲁斯

如果我想比一小时更精确地知道差异怎么办?在发布的问题中,有几小时和几秒钟,所有这些零设置是什么?
2oppin


6
var d1=new Date(2011,0,1); // jan,1 2011
var d2=new Date(); // now

var diff=d2-d1,sign=diff<0?-1:1,milliseconds,seconds,minutes,hours,days;
diff/=sign; // or diff=Math.abs(diff);
diff=(diff-(milliseconds=diff%1000))/1000;
diff=(diff-(seconds=diff%60))/60;
diff=(diff-(minutes=diff%60))/60;
days=(diff-(hours=diff%24))/24;

console.info(sign===1?"Elapsed: ":"Remains: ",
             days+" days, ",
             hours+" hours, ",
             minutes+" minutes, ",
             seconds+" seconds, ",
             milliseconds+" milliseconds.");

4

对不起,但是毫秒级的计算并不可靠。 感谢所有答复,但是我尝试过的几个功能都失败了:1.日期接近今天的日期2.日期为1970年或3.日期为a年。

最适合我的方法,涵盖了所有情况,例如leap年,1970年的临近日期,2月29日等。

var someday = new Date("8/1/1985");
var today = new Date();
var years = today.getFullYear() - someday.getFullYear();

// Reset someday to the current year.
someday.setFullYear(today.getFullYear());

// Depending on when that day falls for this year, subtract 1.
if (today < someday)
{
    years--;
}
document.write("Its been " + years + " full years.");

3

如果您正在使用moment.js,那么查找日期差异非常简单。

var now  = "04/09/2013 15:00:00";
var then = "04/09/2013 14:20:30";

moment.utc(moment(now,"DD/MM/YYYY HH:mm:ss").diff(moment(then,"DD/MM/YYYY HH:mm:ss"))).format("HH:mm:ss")

3
function DateDiff(b, e)
{
    let
        endYear = e.getFullYear(),
        endMonth = e.getMonth(),
        years = endYear - b.getFullYear(),
        months = endMonth - b.getMonth(),
        days = e.getDate() - b.getDate();
    if (months < 0)
    {
        years--;
        months += 12;
    }
    if (days < 0)
    {
        months--;
        days += new Date(endYear, endMonth, 0).getDate();
    }
    return [years, months, days];
}

[years, months, days] = DateDiff(
    new Date("October 21, 1980"),
    new Date("July 11, 2017")); // 36 8 20

3

我认为应该这样做。

let today = new Date();
let form_date=new Date('2019-10-23')
let difference=form_date>today ? form_date-today : today-form_date
let diff_days=Math.floor(difference/(1000*3600*24))

2

这样就可以在没有框架的情况下实现日期之间的差异。

function getDateDiff(dateOne, dateTwo) {
        if(dateOne.charAt(2)=='-' & dateTwo.charAt(2)=='-'){
            dateOne = new Date(formatDate(dateOne));
            dateTwo = new Date(formatDate(dateTwo));
        }
        else{
            dateOne = new Date(dateOne);
            dateTwo = new Date(dateTwo);            
        }
        let timeDiff = Math.abs(dateOne.getTime() - dateTwo.getTime());
        let diffDays = Math.ceil(timeDiff / (1000 * 3600 * 24));
        let diffMonths = Math.ceil(diffDays/31);
        let diffYears = Math.ceil(diffMonths/12);

        let message = "Difference in Days: " + diffDays + " " +
                      "Difference in Months: " + diffMonths+ " " + 
                      "Difference in Years: " + diffYears;
        return message;
     }

    function formatDate(date) {
         return date.split('-').reverse().join('-');
    }

    console.log(getDateDiff("23-04-2017", "23-04-2018"));

1

function daysInMonth (month, year) {
    return new Date(year, month, 0).getDate();
}
function getduration(){

let A= document.getElementById("date1_id").value
let B= document.getElementById("date2_id").value

let C=Number(A.substring(3,5))
let D=Number(B.substring(3,5))
let dif=D-C
let arr=[];
let sum=0;
for (let i=0;i<dif+1;i++){
  sum+=Number(daysInMonth(i+C,2019))
}
let sum_alter=0;
for (let i=0;i<dif;i++){
  sum_alter+=Number(daysInMonth(i+C,2019))
}
let no_of_month=(Number(B.substring(3,5)) - Number(A.substring(3,5)))
let days=[];
if ((Number(B.substring(3,5)) - Number(A.substring(3,5)))>0||Number(B.substring(0,2)) - Number(A.substring(0,2))<0){
days=Number(B.substring(0,2)) - Number(A.substring(0,2)) + sum_alter
}

if ((Number(B.substring(3,5)) == Number(A.substring(3,5)))){
console.log(Number(B.substring(0,2)) - Number(A.substring(0,2)) + sum_alter)
}

time_1=[]; time_2=[]; let hour=[];
 time_1=document.getElementById("time1_id").value
 time_2=document.getElementById("time2_id").value
  if (time_1.substring(0,2)=="12"){
     time_1="00:00:00 PM"
  }
if (time_1.substring(9,11)==time_2.substring(9,11)){
hour=Math.abs(Number(time_2.substring(0,2)) - Number(time_1.substring(0,2)))
}
if (time_1.substring(9,11)!=time_2.substring(9,11)){
hour=Math.abs(Number(time_2.substring(0,2)) - Number(time_1.substring(0,2)))+12
}
let min=Math.abs(Number(time_1.substring(3,5))-Number(time_2.substring(3,5)))
document.getElementById("duration_id").value=days +" days "+ hour+"  hour " + min+"  min " 
}
<input type="text" id="date1_id" placeholder="28/05/2019">
<input type="text" id="date2_id" placeholder="29/06/2019">
<br><br>
<input type="text" id="time1_id" placeholder="08:01:00 AM">
<input type="text" id="time2_id" placeholder="00:00:00 PM">
<br><br>
<button class="text" onClick="getduration()">Submit </button>
<br><br>
<input type="text" id="duration_id" placeholder="days hour min">


这段代码给出了关于天,时间甚至分钟数的准确结果
Maximus Su

希望你们使用它
Maximus Su

-1

如果您只需要显示剩余时间,则此方法就可以正常工作,因为JavaScript使用其时间作为帧,您将获得结束时间-此后的时间RN,我们可以将其除以1000,因为显然是1000帧= 1秒,之后,您可以使用时间的基本数学方法,但是此代码仍然存在问题,由于计算是静态的,因此无法补偿一年中不同的天总数(360/365/366),如果计算后如果时间小于0,则将其设置为null,即使这与您要求的不完全相同,也希望这会有所帮助:)

var now = new Date();
var end = new Date("End Time");
var total = (end - now) ;
var totalD =  Math.abs(Math.floor(total/1000));

var years = Math.floor(totalD / (365*60*60*24));
var months = Math.floor((totalD - years*365*60*60*24) / (30*60*60*24));
var days = Math.floor((totalD - years*365*60*60*24 - months*30*60*60*24)/ (60*60*24));
var hours = Math.floor((totalD - years*365*60*60*24 - months*30*60*60*24 - days*60*60*24)/ (60*60));
var minutes = Math.floor((totalD - years*365*60*60*24 - months*30*60*60*24 - days*60*60*24 - hours*60*60)/ (60));
var seconds = Math.floor(totalD - years*365*60*60*24 - months*30*60*60*24 - days*60*60*24 - hours*60*60 - minutes*60);

var Y = years < 1 ? "" : years + " Years ";
var M = months < 1 ? "" : months + " Months ";
var D = days < 1 ? "" : days + " Days ";
var H = hours < 1 ? "" : hours + " Hours ";
var I = minutes < 1 ? "" : minutes + " Minutes ";
var S = seconds < 1 ? "" : seconds + " Seconds ";
var A = years == 0 && months == 0 && days == 0 && hours == 0 && minutes == 0 && seconds == 0 ? "Sending" : " Remaining";

document.getElementById('txt').innerHTML = Y + M + D + H + I + S + A;
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.