Làm cách nào để tính chênh lệch ngày trong JavaScript?


181

Tôi muốn tính chênh lệch ngày theo ngày, giờ, phút, giây, mili giây, nano giây. Tôi làm nó như thế nào?



1
Các giải pháp dưới đây sẽ bị phá vỡ nếu hai ngày liên quan ở các múi giờ khác nhau. Xem câu hỏi tại để biết giải pháp stackoverflow.com/questions/3224834/ cấp chính xác hơn ?
Shyam Habarakada

Câu trả lời:


219

Giả sử bạn có hai Dateđối tượng , bạn chỉ cần trừ chúng để có sự khác biệt tính bằng mili giây:

var difference = date2 - date1;

Từ đó, bạn có thể sử dụng số học đơn giản để rút ra các giá trị khác.


38
Đây là câu trả lời đúng. Ví dụ: để có sự khác biệt về số ngày làm Math.floor((date2 - date1) / (1000*60*60*24))- đối với sự khác biệt trong bất kỳ đơn vị nào khác, hãy điều chỉnh mẫu số (giá trị cơ bản được tính bằng ms).
trisweb

33
Không có số học "đơn giản" để chuyển đổi mili giây sang năm. Bạn phải biết năm bissextile, múi giờ và một số ngày có 23 hoặc 25 giờ. Một số năm có 365,25 ngày, vì vậy không có số học đơn giản ở đây (vẫn đang tìm kiếm một giải pháp chính xác).
Alexandre Salomé

6
@Alexandre: Câu hỏi không bao giờ được hỏi trong nhiều năm. Thật vậy, tính toán chênh lệch năm là không cần thiết. Tuy nhiên, trong nhiều ngày, điều này là chính xác, giả sử ngày nằm trong cùng múi giờ (một giả định không hợp lý). Theo như tôi biết, một ngày được xác định là 24 giờ và bất kỳ "biến thể" nào trong đó do Giờ tiết kiệm ánh sáng ban ngày thực sự là một sự thay đổi của các múi giờ. Nếu bạn chưa phân biệt được các múi giờ, cố gắng tìm ra sự khác biệt về thời gian sẽ khiến bạn rơi vào thế giới bị tổn thương, nhất là vì việc chuyển đổi DST 'lặp lại' thời gian. Ở trong một múi giờ, mặc dù, và tất cả đều hoạt động.
icktoofay

12
@ trisweb, thậm chí một cái gì đó đơn giản như nhận được sự khác biệt trong ngày còn phức tạp hơn bình luận của bạn. Có bao nhiêu ngày từ 10 giờ tối thứ ba đến 9 giờ sáng thứ tư? Thuật toán của bạn nói 0. Người khác có thể nghĩ 1.
RobG

Những người theo thuyết tương đối @RobG thậm chí có thể nghĩ nhiều hơn 1 hoặc ít hơn 0. Tất cả phụ thuộc vào người quan sát.
Bystander vô tội

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));

Mã mẫu lấy từ đây .


Điều này chỉ trả về chênh lệch ngày trong định dạng đã cho nếu được sử dụng như một bộ đếm duy nhất. Ví dụ: nếu bạn muốn 3 tháng 4 ngày và 5 giờ thì nó sẽ KHÔNG tạo ra những kết quả đó. Nhiều hơn trong dòng 3 tháng 96 ngày và rất nhiều giờ.
Joris Kroos

30

Một giải pháp khác là chuyển đổi sự khác biệt sang một đối tượng Ngày mới và lấy năm đó (khác với năm 1970), tháng, ngày, v.v.

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

Vì vậy, sự khác biệt giống như "3 năm 6 tháng và 4 ngày". Nếu bạn muốn có sự khác biệt trong một phong cách dễ đọc của con người, điều đó có thể giúp bạn.


Nó không phải là ý nghĩa! Chúng tôi muốn sự khác biệt WHOLE! Trong examp này, differene trong ngày là 1281, không phải 4!
chaim.dev

3
@ chaim.dev "Nếu bạn muốn có sự khác biệt trong phong cách dễ đọc của con người, điều đó có thể giúp bạn."
Murat Çorlu

7
Điều này không đáng tin cậy. Nó không tính đến các độ dài tháng khác nhau, hoặc năm nhuận và các bất thường khác.
Marc Durdin

2
Cảm ơn Murat, giải pháp này đã giải quyết vấn đề của tôi. Điều tôi thực sự muốn là Nó phải hoạt động theo cách tương tự như php.
Ritesh Patadiya

27

Biểu hiện như "sự khác biệt trong ngày" không bao giờ đơn giản như chúng có vẻ. Nếu bạn có những ngày sau:

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

chênh lệch về thời gian là 2 phút, "chênh lệch theo ngày" là 1 hay 0? Các vấn đề tương tự phát sinh đối với bất kỳ biểu hiện nào của sự khác biệt về tháng, năm hoặc bất cứ điều gì kể từ năm, tháng và ngày có độ dài khác nhau và thời gian khác nhau (ví dụ: ngày bắt đầu tiết kiệm ánh sáng ban ngày ngắn hơn 1 giờ so với ngày thường và ngắn hơn hai giờ so với ngày nó kết thúc).

Đây là một hàm cho sự khác biệt về số ngày mà bỏ qua thời gian, tức là cho những ngày trên, nó trả về 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 );
}

Điều này có thể ngắn gọn hơn:

/*  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
@ rudeovskizebear, được thử nghiệm trên IE, Firefox và Safari, hoạt động tốt. Nó sử dụng ECMAScript cơ bản mà tôi mong đợi hoạt động trong bất kỳ trình duyệt nào, điều gì không phù hợp với bạn?
RobG

Tôi đã đặt nó trên một trang thử nghiệm và nó hoạt động tốt trong chrome, nhưng tôi đã tiếp tục trở lại null trong IE9 và FF mới nhất
mnsr

@ RafiB. Vay Tôi không biết bạn nghĩ cái này chính xác hơn cái kia như thế nào, về cơ bản chúng giống nhau, tức là tính toán sự khác biệt trong cả ngày bằng cách sử dụng giá trị thời gian UTC. Sự mơ hồ trong câu hỏi không được làm rõ. Nếu có, nó có thể dẫn đến một giải pháp khác.
RobG

@RobG Vui lòng chỉnh sửa các ví dụ trong các nhận xét về giải pháp ngắn gọn hơn. Tháng nên là '12' chứ không phải '22'
S.aad

1
@ IgorKudryashov, xin lỗi, tôi chỉ không nhận được nó. Năm 2000 là một năm nhuận, vì vậy ngày 28 tháng 2 năm 2000 đến ngày 28 tháng 2 năm 2001 là 365 ngày. Trong một năm không nhảy vọt, đó là 365 ngày. Tôi đã thêm một số ví dụ.
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>

Không giúp tôi. Không thể kéo dài điều này đến tháng hoặc năm theo cùng một cách tiếp cận.
tomazahlin

9

sử dụng Moment.js cho tất cả các phép tính thời gian liên quan đến JavaScript của bạn

Trả lời câu hỏi của bạn là:

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

Chi tiết đầy đủ có thể được tìm thấy ở đây


4
Và nắm lấy hơn 400 Kb cho một sự khác biệt ngày chỉ.
Romeo Mihalcea

@RomeoMihalcea Khoảnh khắc được thu nhỏ hiện tại 2.22.2 với một ngôn ngữ là 53 KB, được nén 17 KB. Tôi hiểu mối quan tâm của bạn mặc dù. Đó là một thư viện khổng lồ để sử dụng cho một chức năng đơn giản, nhưng nó quan tâm đến rất nhiều điều kỳ quặc liên quan đến ngày / giờ mà nó thường có giá trị.
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      
}

Cảm ơn các giải pháp :)
bhagirathi

Hầu hết các giải pháp mà tôi thấy hoặc không hoạt động hoặc quá dài. Giải pháp của bạn là đơn giản nhất cho đến nay và hoạt động chính xác như dự định! Chúc mừng :)
Bruce

Điều gì xảy ra nếu tôi muốn biết sự khác biệt với chính xác hơn một giờ? trong câu hỏi bài viết có giờ và giây, điều gì cho tất cả các số không này?
2oppin

8

Với khoảnh khắc thật đơn giản:

moment("2016-04-08").fromNow();

1
khoảnh khắc thật tuyệt vời :)
Kami

Câu trả lời tốt đẹp, nhưng có lẽ quá mức cho tình huống cụ thể này.
HappyDog

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

Xin lỗi nhưng tính toán mili giây không đáng tin cậy Cảm ơn tất cả các phản hồi, nhưng một số chức năng tôi đã thử bị lỗi vào ngày 1. Một ngày gần ngày hôm nay 2. Một ngày trong năm 1970 hoặc 3. Một ngày trong năm nhuận.

Cách tiếp cận phù hợp nhất với tôi và bao gồm tất cả các kịch bản, ví dụ như năm nhuận, gần ngày vào năm 1970, feb 29, v.v.

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

Nếu bạn đang sử dụng Moment.js thì việc tìm ngày khác biệt là khá đơn giản.

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

Tôi nghĩ rằng điều này nên làm điều đó.

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

Đây là cách bạn có thể thực hiện sự khác biệt giữa các ngày mà không cần khung.

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">


Mã này cho kết quả chính xác về việc không có ngày, thời gian và thậm chí là vài phút
Maximus Su

Hy vọng các bạn sử dụng nó
Maximus Su

0

Ok, có rất nhiều cách bạn có thể làm điều đó. Có, bạn có thể sử dụng JS cũ đơn giản. Cứ thử đi:

let dt1 = new Date()
let dt2 = new Date()

Hãy mô phỏng đoạn văn bằng Date.prototype.setMinutes và đảm bảo rằng chúng tôi nằm trong phạm vi.

dt1.setMinutes(7)
dt2.setMinutes(42)
console.log('Elapsed seconds:',(dt2-dt1)/1000)

Ngoài ra, bạn có thể sử dụng một số thư viện như js-joda , nơi bạn có thể dễ dàng thực hiện những việc như thế này (trực tiếp từ tài liệu):

var dt1 = LocalDateTime.parse("2016-02-26T23:55:42.123");
var dt2 = dt1
  .plusYears(6)
  .plusMonths(12)
  .plusHours(2)
  .plusMinutes(42)
  .plusSeconds(12);

// obtain the duration between the two dates
dt1.until(dt2, ChronoUnit.YEARS); // 7
dt1.until(dt2, ChronoUnit.MONTHS); // 84
dt1.until(dt2, ChronoUnit.WEEKS); // 356
dt1.until(dt2, ChronoUnit.DAYS); // 2557
dt1.until(dt2, ChronoUnit.HOURS); // 61370
dt1.until(dt2, ChronoUnit.MINUTES); // 3682242
dt1.until(dt2, ChronoUnit.SECONDS); // 220934532

Có rất nhiều thư viện ofc, nhưng js-joda có thêm phần thưởng là có sẵn trong Java, nơi nó đã được thử nghiệm rộng rãi. Tất cả những bài kiểm tra đã được chuyển sang js-joda, nó cũng không thay đổi.


-1

điều này sẽ hoạt động tốt nếu bạn chỉ cần hiển thị thời gian còn lại, vì JavaScript sử dụng các khung cho thời gian của nó, bạn sẽ nhận được Thời gian kết thúc của mình - Thời gian RN sau đó chúng ta có thể chia cho 1000 vì rõ ràng là 1000 khung = 1 giây, sau đó bạn có thể sử dụng toán cơ bản về thời gian, nhưng vẫn có một vấn đề với mã này, vì phép tính là tĩnh, nó không thể bù cho tổng số ngày khác nhau trong một năm (360/365/366), bó NẾU sau khi tính toán sẽ biến nó thành null nếu thời gian thấp hơn 0, hy vọng điều này sẽ có ích mặc dù nó không chính xác như những gì bạn đang hỏi :)

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;
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.