Come calcolare la differenza di data in JavaScript?


181

Voglio calcolare la differenza di data in giorni, ore, minuti, secondi, millisecondi, nanosecondi. Come posso farlo?



1
Le soluzioni seguenti si interromperanno se le due date coinvolte si trovano in fusi orari diversi. Vedi la domanda per una soluzione più accurata stackoverflow.com/questions/3224834/… ?
Shyam Habarakada,

Risposte:


219

Supponendo che tu abbia due Dateoggetti , puoi semplicemente sottrarli per ottenere la differenza in millisecondi:

var difference = date2 - date1;

Da lì, puoi usare l'aritmetica semplice per derivare gli altri valori.


38
Questa è quindi la risposta giusta. Ad esempio: per ottenere la differenza in giorni, Math.floor((date2 - date1) / (1000*60*60*24))per differenza in qualsiasi altra unità, regolare il denominatore (il valore di base è in ms).
trisweb,

33
Non esiste un'aritmetica "semplice" per convertire millisecondi in anni. Devi essere consapevole dell'anno bisestile, del fuso orario e alcuni giorni hanno 23 o 25 ore. Alcuni anni hanno 365,25 giorni, quindi non esiste una semplice aritmetica qui (ancora alla ricerca di una soluzione accurata).
Alexandre Salomé,

6
@Alexandre: la domanda non viene mai posta per anni. In effetti, il calcolo delle differenze annue non è banale. Per giorni, tuttavia, è corretto, supponendo che le date siano nello stesso fuso orario (un presupposto non irragionevole). Per quanto ne so, un giorno è definito come 24 ore e qualsiasi "variazione" in quanto dovuta all'ora legale è in realtà un cambio di fusi orari. Se non distingui già tra i fusi orari, provare a capire una differenza di tempo ti metterà in un mondo di dolore, anche perché il passaggio all'ora legale "ripete" il tempo. Rimani in un fuso orario, però, e funziona tutto.
icktoofay,

12
@ trisweb: anche qualcosa di semplice come ottenere una differenza in giorni è più complesso del tuo commento. Quanti giorni tra le 22:00 martedì e le 9:00 mercoledì? Il tuo algoritmo dice 0. Altri potrebbero pensare 1.
RobG

I relativisti di @RobG potrebbero persino pensare più di 1 o meno di 0. Tutto dipende dall'osservatore.
Innocent Bystander il

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

Esempio di codice preso da qui .


Ciò restituisce la differenza di data nel formato specificato solo se utilizzato come contatore singolo. Ad esempio, se vuoi 3 mesi 4 giorni e 5 ore NON produrrà questi risultati. Più nella linea di 3 mesi 96 giorni e molte ore.
Joris Kroos,

30

Un'altra soluzione è convertire la differenza in un nuovo oggetto Date e ottenere l'anno di quella data (diff dal 1970), il mese, il giorno ecc.

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

Quindi la differenza è come "3 anni e 6 mesi e 4 giorni". Se vuoi fare la differenza in uno stile leggibile dall'uomo, questo può aiutarti.


Non è il significato! Vogliamo la differenza INTERA! In questo esempio, il differenziale in giorni è 1281, non 4!
chaim.dev,

3
@ chaim.dev "Se vuoi fare la differenza in uno stile leggibile dall'uomo, questo può aiutarti."
Murat Çorlu,

7
Questo non è affidabile. Non tiene conto della durata variabile dei mesi, degli anni bisestili e di altre anomalie.
Marc Durdin,

2
Grazie Murat, questa soluzione ha risolto il mio problema. Quello che voglio davvero che deve funzionare allo stesso modo di PHP.
Ritesh Patadiya,

27

Espressioni come "differenza nei giorni" non sono mai così semplici come sembrano. Se hai le seguenti date:

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

la differenza nel tempo è di 2 minuti, la "differenza in giorni" dovrebbe essere 1 o 0? Problemi analoghi sorgono per qualsiasi espressione della differenza in mesi, anni o qualsiasi cosa da anni, mesi e giorni di diversa lunghezza e tempi diversi (ad esempio il giorno in cui inizia l'ora legale è 1 ora più breve del solito e due ore più breve del giorno che finisce).

Ecco una funzione per una differenza in giorni che ignora l'ora, ovvero per le date sopra restituisce 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 );
}

Questo può essere più conciso:

/*  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: testato in Internet Explorer, Firefox e Safari, funziona perfettamente. Utilizza l'ECMAScript di base che mi aspetto di funzionare in qualsiasi browser, cosa non funziona per te?
RobG,

L'ho messo su una pagina di prova e ha funzionato bene in Chrome, ma ho continuato a tornare nullo in IE9 e l'ultimo FF
mnsr

@ RafiB. — Non so come pensi che uno sia più preciso dell'altro, fanno essenzialmente la stessa cosa, cioè calcolano la differenza in giorni interi usando un valore orario UTC. L'ambiguità nella domanda non è stata chiarita. Se lo fosse, potrebbe portare a una soluzione diversa.
RobG

@RobG Modifica gli esempi nei commenti di una soluzione più concisa. Il mese dovrebbe essere '12' non '22'
S.aad

1
@ IgorKudryashov — scusa, non capisco. Il 2000 è un anno bisestile, quindi dal 28 febbraio 2000 al 28 febbraio 2001 è di 366 giorni. In un anno non bisestile, sono 365 giorni. Ho aggiunto altri esempi.
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>

Non mi aiuta Non è possibile estenderlo a mesi o anni con lo stesso approccio.
Tomazahlin,

9

usa Moment.js per tutto il calcolo della data e dell'ora relativo a JavaScript

La risposta alla tua domanda è:

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

I dettagli completi sono disponibili qui


4
E abbraccia i 400+ Kb in più per una semplice differenza di data.
Romeo Mihalcea,

@RomeoMihalcea Il momento attuale minimizzato.js 2.22.2 con una locale è 53 KB, 17 KB compressi con gzip. Capisco la tua preoccupazione però. È un'enorme libreria da utilizzare per una semplice funzione, ma si occupa di così tante stranezze relative a data / ora che spesso ne vale la pena.
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      
}

Grazie per le soluzioni :)
bhagirathi, il

La maggior parte delle soluzioni che ho trovato non funzionano o sono troppo lunghe. La tua soluzione è la più semplice finora e funziona esattamente come previsto! Saluti :)
Bruce

cosa succede se voglio sapere la differenza con più di un'ora precisa? nella domanda post ci sono ore e secondi, cosa succede per tutte queste azzeramenti?
aprile


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

Siamo spiacenti ma il calcolo dei millisecondi non è affidabile Ci Grazie per tutte le risposte, ma alcune delle funzioni che ho provato non riescono su 1. Una data vicina alla data odierna 2. Una data nel 1970 o 3. Una data in un anno bisestile.

Approccio che ha funzionato meglio per me e copre tutti gli scenari, ad esempio l'anno bisestile, la data prossima al 1970, il 29 febbraio, ecc.

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

Se stai usando moment.js, è abbastanza semplice trovare la differenza di data.

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

Penso che questo dovrebbe farlo.

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

Ecco come è possibile implementare la differenza tra le date senza un framework.

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


Questo codice fornisce risultati accurati sul numero di giorni, ore e persino minuti
Massimo,

Spero che voi ragazzi usarlo
Maximus Su

0

Ok, ci sono molti modi per farlo. Sì, puoi usare semplicemente il vecchio JS. Prova:

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

Emuliamo il passaggio usando Date.prototype.setMinutes e assicuriamoci di essere nel raggio d'azione.

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

In alternativa puoi usare alcune librerie come js-joda , dove puoi facilmente fare cose come queste (direttamente dai documenti):

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

Ci sono molte più librerie ofc, ma js-joda ha un ulteriore vantaggio di essere disponibile anche in Java, dove è stato ampiamente testato. Tutti questi test sono stati migrati su js-joda, è anche immutabile.


-1

questo dovrebbe funzionare bene se hai solo bisogno di mostrare il tempo rimasto, poiché JavaScript utilizza i frame per il suo tempo avrai il tuo End Time - The Time RN dopo che possiamo dividerlo per 1000 poiché apparentemente 1000 frame = 1 secondi, dopodiché puoi usare la matematica di base del tempo, ma c'è ancora un problema con questo codice, poiché il calcolo è statico, non può compensare il totale dei diversi giorni in un anno (360/365/366), il gruppo di Se dopo il calcolo è necessario renderlo nullo se il tempo è inferiore a 0, spero che questo aiuti anche se non è esattamente quello che stai chiedendo :)

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;
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.