Як розрахувати різницю дат у JavaScript?


181

Я хочу обчислити різницю дат у днях, годинах, хвилинах, секундах, мілісекундах, наносекундах. Як я можу це зробити?



1
Наведені нижче рішення будуть порушені, якщо дві зазначені дати перебувають у різних часових поясах. Дивіться питання на адресу для більш точного рішення stackoverflow.com/questions/3224834/… ?
Шям Хабаракада

Відповіді:


219

Припустимо, що у вас є два Dateоб'єкти , ви можете просто відняти їх, щоб отримати різницю в мілісекундах:

var difference = date2 - date1;

Звідти ви можете використовувати просту арифметику для отримання інших значень.


38
Це правильна відповідь. Наприклад: щоб отримати різницю в днях Math.floor((date2 - date1) / (1000*60*60*24))- для різниці в будь-якій іншій одиниці відрегулюйте знаменник (базове значення в мс).
trisweb

33
Не існує "простої" арифметики для перетворення мілісекунд у роки. Ви повинні бути в курсі бісексуального року, часового поясу, а деякі дні мають 23 або 25 годин. Деякі роки мають 365,25 днів, тому тут немає простої арифметики (все ще шукаю точне рішення).
Олександр Саломе

6
@Alexandre: Запитання ніколи не задавалося роками. Дійсно, обчислення різниць за рік нетривіально. Однак цілком правильним є припущення, що дати перебувають у одному часовому поясі (не необгрунтоване припущення). Наскільки я знаю, день визначається як 24 години, і будь-яка «різниця» у зв'язку із літнім часовим часом фактично є перемиканням часових поясів. Якщо ви вже не розрізняєте часові пояси, спроба з'ясувати різницю у часі поставить вас у світ болю, не в останню чергу через те, що перехід DST "повторює" час. Будьте в одному часовому поясі, і все працює.
icktoofay

12
@ trisweb - навіть щось таке просте, як визначити різницю в днях складніше, ніж ваш коментар. Скільки днів між 22:00 вівторок і 9:00 ранку? Ваш алгоритм говорить 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

3
@ chaim.dev "Якщо ви хочете змінити людський стиль, який читається, це може вам допомогти."
Murat luorlu

7
Це не є надійним. Він не враховує різну тривалість місяця, або високосні роки та інші аномалії.
Марк Дурдін

2
Дякую Мурат, це рішення вирішило мою проблему. Що я дуже хочу, щоб це повинно працювати так само, як це робить php.
Ritesh Patadiya

27

Вирази на кшталт "різниця в днях" ніколи не є настільки простими, як здаються. Якщо у вас є наступні дати:

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

різниця у часі - 2 хвилини, чи "різниця в днях" повинна бути 1 або 0? Подібні проблеми виникають при будь-якому вираженні різниці в місяцях, роках або будь-якому, тому що роки, місяці та дні мають різну тривалість і різний час (наприклад, день, коли починається літній час, на 1 годину коротший, ніж зазвичай, і на дві години коротший, ніж день, коли це закінчується).

Ось функція різниці в днях, яка ігнорує час, тобто для вищезазначених дат вона повертає 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
@ rudeovskizebear - перевірена на IE, Firefox та Safari, працює чудово. Він використовує базовий ECMAScript, який я б очікував працювати в будь-якому браузері, що для вас не працює?
RobG

Я поставив це на тестову сторінку, і він добре працював у хромі, але я продовжував отримувати нульові показники в IE9 та останньому FF
mnsr

@ RafiB. - Я не знаю, наскільки ви вважаєте, що один є більш точним, ніж інший, вони роблять по суті те саме, тобто обчислюють різницю за цілі дні, використовуючи значення часу UTC. Неоднозначність у питанні не з'ясована. Якщо це було, це може призвести до іншого рішення.
RobG

@RobG Будь ласка, відредагуйте приклади в коментарях більш короткого рішення. Місяць має бути "12", а не 22,
С.аад,

1
@ Ігор Кудряшов - вибачте, я просто не отримую цього. 2000 рік - високосний рік, тому 28 лютого 2000 р. По 28 лютого 2001 р. - 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+ Кб за різницю в даті.
Ромео Міхалча

@RomeoMihalcea Поточний мінімізований момент.js 2.22.2 з однією локальною точкою - 53 КБ, 17 кбіт gzipped. Я розумію, що ти хвилюєшся. Це величезна бібліотека, яку можна використовувати для однієї простої функції, але вона піклується про стільки примх, пов'язаних з датою / часом, що часто того варто.
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

Вибачте, але плоский мілісекундний розрахунок не є надійним Дякую за всі відповіді, але деякі функції, які я намагався, не спрацьовують жодної дати.

Підхід, який найкраще працював для мене, і охоплює всі сценарії, наприклад, високосний рік, приблизна дата в 1970 році, 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

0

Гаразд, існує маса способів зробити це. Так, ви можете використовувати звичайний старий JS. Просто спробуйте:

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

Давайте емулюємо прохід, використовуючи Date.prototype.setMinutes і переконайтеся, що ми знаходимося в діапазоні.

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

Крім того, ви можете використовувати якусь бібліотеку на зразок js-joda , де ви можете легко робити такі речі (безпосередньо з документів):

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

Більше бібліотек ofc є набагато більше, але js-joda має додатковий бонус за доступність також на Java, де він пройшов широку перевірку. Усі ці тести були перенесені на js-joda, це також незмінне.


-1

це має спрацювати чудово, якщо вам просто потрібно показати час, який залишився, оскільки JavaScript використовує кадри для свого часу, ви отримаєте свій кінцевий час - час RN, після цього ми можемо розділити його на 1000, оскільки, мабуть, 1000 кадрів = 1 секунда, після цього ви можете використовувати основну математику часу, але все ще існує проблема з цим кодом, оскільки обчислення є статичним, він не може компенсувати загальну кількість днів у році (360/365/366), купу ЯКЩО після обчислення потрібно зробити його недійсним, якщо час нижчий за 0, сподівайтеся, що це допоможе, хоча це не зовсім те, що ви просите :)

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;
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.