Jak obliczyć różnicę dat w JavaScript?

181

Chcę obliczyć różnicę daty w dniach, godzinach, minutach, sekundach, milisekundach, nanosekundach. Jak mogę to zrobić?

Farhan Siddiqui
źródło
1
możliwy duplikat Uzyskaj różnicę między 2 datami w javascript?
Anderson Green
1
Poniższe rozwiązania ulegną awarii, jeśli dwie zaangażowane daty będą miały różne strefy czasowe. Zobacz pytanie na bardziej dokładne rozwiązanie stackoverflow.com/questions/3224834/... ?
Shyam Habarakada

Odpowiedzi:

219

Zakładając, że masz dwa Dateobiekty , możesz je odjąć, aby uzyskać różnicę w milisekundach:

var difference = date2 - date1;

Stamtąd możesz użyć prostej arytmetyki, aby uzyskać inne wartości.

icktoofay
źródło
38
To jest właściwa odpowiedź. Np .: aby uzyskać różnicę w dniach, wykonaj Math.floor((date2 - date1) / (1000*60*60*24))- dla różnicy w dowolnej innej jednostce, dostosuj mianownik (wartość bazowa jest w ms).
trisweb
33
Nie ma „prostej” arytmetyki do przeliczania milisekund na lata. Musisz być świadomy roku bissextile, strefy czasowej, a niektóre dni mają 23 lub 25 godzin. Niektóre lata mają 365,25 dni, więc nie ma tutaj prostej arytmetyki (wciąż szukającej dokładnego rozwiązania).
Alexandre Salomé
6
@Alexandre: Pytanie to nie było zadawane przez lata. Rzeczywiście, obliczanie różnic lat nie jest łatwe. Przez kilka dni jest to jednak poprawne, zakładając, że daty znajdują się w tej samej strefie czasowej (nieuzasadnione założenie). O ile mi wiadomo, dzień jest definiowany jako 24 godziny, a każda „zmiana” z tego powodu ze względu na czas letni jest w rzeczywistości zmianą stref czasowych. Jeśli nie rozróżniasz już stref czasowych, próba znalezienia różnicy czasu wprowadzi cię w świat bólu, zwłaszcza dlatego, że czas przełączania DST „powtarza się”. Pozostań jednak w jednej strefie czasowej i wszystko działa.
icktoofay
12
@ trisweb - nawet coś tak prostego, jak uzyskanie różnicy dni, jest bardziej złożone niż Twój komentarz. Ile dni od 22:00 we wtorek do 9:00 w środę? Twój algorytm mówi 0. Inni mogą myśleć 1.
RobG
Relatywiści @RobG mogą nawet myśleć więcej niż 1 lub mniej niż 0. Wszystko zależy od obserwatora.
Innocent Bystander
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));

Próbka kodu pobrana stąd .

Paresh Mayani
źródło
Zwraca różnicę daty w danym formacie, jeśli jest używany jako pojedynczy licznik. Na przykład, jeśli chcesz 3 miesiące 4 dni i 5 godzin, NIE przyniesie to wyników. Więcej w ciągu 3 miesięcy 96 dni i wiele godzin.
Joris Kroos
30

Innym rozwiązaniem jest konwersja różnicy na nowy obiekt Date i uzyskanie daty roku (różni się od 1970), miesiąca, dnia itp.

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

Różnica jest jak „3 lata i 6 miesięcy i 4 dni”. Jeśli chcesz zmienić styl czytelny dla człowieka, może ci to pomóc.

Murat Çorlu
źródło
To nie ma znaczenia! Chcemy CAŁĄ różnicę! W tym przykładzie różnica dni wynosi 1281, a nie 4!
chaim.dev,
3
@ chaim.dev „Jeśli chcesz zmienić styl czytelny dla człowieka, może ci to pomóc”.
Murat Çorlu
7
To nie jest wiarygodne. Nie uwzględnia różnych długości miesięcy, lat przestępnych i innych anomalii.
Marc Durdin,
2
Dzięki Murat, to rozwiązanie rozwiązało mój problem. To, czego naprawdę chcę, to musi działać tak samo jak PHP.
Ritesh Patadiya
27

Wyrażenia takie jak „różnica dni” nigdy nie są tak proste, jak się wydają. Jeśli masz następujące daty:

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

różnica w czasie wynosi 2 minuty, czy „różnica w dniach” powinna wynosić 1 czy 0? Podobne problemy pojawiają się przy wyrażaniu różnicy w miesiącach, latach lub cokolwiek innego, ponieważ lata, miesiące i dni mają różne długości i różne czasy (np. Dzień, w którym zaczyna się czas letni, jest o 1 godzinę krótszy niż zwykle i o dwie godziny krótszy niż dzień, w którym kończy się).

Oto funkcja różnicy dni, która ignoruje czas, tzn. Dla powyższych dat zwraca 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 );
}

Może to być bardziej zwięzłe:

/*  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>');
});

RobG
źródło
1
@ rudeovskizebear - przetestowany w IE, Firefox i Safari, działa dobrze. Korzysta z podstawowego skryptu ECMAScript, który powinien działać w dowolnej przeglądarce, co nie działa dla Ciebie?
RobG
Umieściłem go na stronie testowej, i działało dobrze w chrome, ale nadal otrzymywałem zero w IE9 i najnowszym FF
mnsr
@ RafiB. - Nie wiem, jak według ciebie jedno jest dokładniejsze od drugiego, robią one zasadniczo to samo, tj. Obliczają różnicę w całych dniach przy użyciu wartości czasu UTC. Niejednoznaczność pytania nie została wyjaśniona. Jeśli tak, może to prowadzić do innego rozwiązania.
RobG
@RobG Edytuj przykłady w komentarzach bardziej zwięzłego rozwiązania. Miesiąc powinien wynosić „12”, a nie „22”
S.aad
1
@ IgorKudryashov - przepraszam, po prostu tego nie rozumiem. 2000 jest rokiem przestępnym, więc 28 lutego 2000 r. Do 28 lutego 2001 r. To 366 dni. W roku bez przestępowania jest to 365 dni. Dodałem więcej przykładów.
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>
Anadi Kumar
źródło
Nie pomaga mi Nie można przedłużyć tego do miesięcy lub lat w tym samym podejściu.
tomazahlin
9

użyj Moment.js do wszystkich obliczeń daty i godziny związanych z JavaScript

Odpowiedź na twoje pytanie brzmi:

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

Pełne szczegóły można znaleźć tutaj

Basant Sahu
źródło
4
I skorzystaj z dodatkowych 400+ Kb za zwykłą różnicę dat.
Romeo Mihalcea,
@RomeoMihalcea Bieżący minimalny moment.js 2.22.2 z jednym ustawieniem regionalnym to 53 KB, 17 KB zgzipowany. Rozumiem jednak twoją troskę. Jest to ogromna biblioteka do użycia dla jednej prostej funkcji, ale zajmuje się tak wieloma dziwactwami związanymi z datą / czasem, że często warto.
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      
}
użytkownik2513608
źródło
Dzięki za rozwiązania :)
bhagirathi
Większość rozwiązań, które znalazłem, albo nie działają, albo są zbyt długie. Twoje rozwiązanie jest jak dotąd najprostsze i działa dokładnie zgodnie z przeznaczeniem! Na zdrowie :)
Bruce
co jeśli chcę poznać różnicę z dokładnością większą niż godzinę? w pytaniu postowym są godziny i sekundy, a co z tymi wszystkimi ustawieniami zerowymi?
2oppin
8

Z momentjs jest to proste:

moment("2016-04-08").fromNow();
Josh LaMar
źródło
1
moment.js jest niesamowity! :)
Kami,
Dobra odpowiedź, ale prawdopodobnie przesada w tej konkretnej sytuacji.
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.");
Andrew D.
źródło
4

Przepraszam, ale obliczenia z płaską milisekundą nie są wiarygodne. Dziękujemy za wszystkie odpowiedzi, ale niektóre z funkcji, które wypróbowałem, zawiodły: 1. Data w pobliżu dzisiejszej daty 2. Data w 1970 lub 3. Data w roku przestępnym.

Podejście, które najlepiej dla mnie działało i obejmuje wszystkie scenariusze, np. Rok przestępny, data zbliżona do 1970 r., 29 lutego itp.

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.");
jaiveeru
źródło
3

Jeśli używasz pliku mom.js, łatwo jest znaleźć różnicę dat.

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")
James Hawkings
źródło
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
Alexander Chernosvitov
źródło
3

Myślę, że to powinno to zrobić.

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))
Ebuka Joseph Akeru
źródło
2

W ten sposób można wprowadzić różnicę między datami bez ram.

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"));
Aravinda Meewalaarachchi
źródło
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
źródło
Ten kod podaje dokładne wyniki dotyczące liczby dni, godzin, a nawet minut
Maximus Su
Mam nadzieję, że go wykorzystacie
Maximus Su
0

Ok, możesz to zrobić na wiele sposobów. Tak, możesz użyć zwykłego starego JS. Spróbuj:

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

Naśladujmy fragment przy użyciu Date.prototype.setMinutes i upewnijmy się, że jesteśmy w zasięgu.

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

Alternatywnie możesz użyć biblioteki takiej jak js-joda , w której możesz łatwo robić takie rzeczy (bezpośrednio z dokumentów):

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

Jest o wiele więcej bibliotek ofc, ale js-joda ma dodatkową zaletę bycia dostępnym również w Javie, gdzie został gruntownie przetestowany. Wszystkie te testy zostały przeniesione do js-joda, jest również niezmienne.

mwojtera
źródło
-1

powinno to działać dobrze, jeśli chcesz pokazać, ile czasu pozostało, ponieważ JavaScript używa ramek na swój czas, otrzymasz czas zakończenia - czas RN, po którym możemy go podzielić przez 1000, ponieważ najwyraźniej 1000 ramek = 1 sekunda, potem możesz użyć podstawowej matematyki czasu, ale kod nadal występuje problem, ponieważ obliczenia są statyczne, nie można zrekompensować całkowitej sumy dni w roku (360/365/366) JEŻELI po obliczeniach ma być zerowe, jeśli czas jest krótszy niż 0, mam nadzieję, że to pomaga, nawet jeśli nie jest to dokładnie to, o co pytasz :)

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;
KratzXD
źródło