¿Cómo calcular la diferencia de fecha en JavaScript?

181

Quiero calcular la diferencia de fechas en días, horas, minutos, segundos, milisegundos, nanosegundos. ¿Cómo puedo hacerlo?

Farhan Siddiqui
fuente
1
posible duplicado de Obtener diferencia entre 2 fechas en javascript?
Anderson Green
1
Las soluciones a continuación se romperán si las dos fechas involucradas están en diferentes zonas horarias. Consulte la pregunta en para una solución más precisa stackoverflow.com/questions/3224834/… ?
Shyam Habarakada

Respuestas:

219

Suponiendo que tiene dos Dateobjetos , puede restarlos para obtener la diferencia en milisegundos:

var difference = date2 - date1;

A partir de ahí, puede usar aritmética simple para derivar los otros valores.

icktoofay
fuente
38
Esta es la respuesta correcta. Por ejemplo: para obtener la diferencia en días Math.floor((date2 - date1) / (1000*60*60*24)), para la diferencia en cualquier otra unidad, ajuste el denominador (el valor base está en ms).
trisweb
33
No hay aritmética "simple" para convertir milisegundos a años. Debe tener en cuenta el año bissextil, la zona horaria y algunos días tienen 23 o 25 horas. Algunos años tienen 365,25 días, por lo que no hay una aritmética simple aquí (todavía buscando una solución precisa).
Alexandre Salomé
66
@Alexandre: La pregunta nunca se hizo por años. De hecho, calcular las diferencias anuales no es trivial. Sin embargo, durante días es correcto, suponiendo que las fechas estén en la misma zona horaria (una suposición no irrazonable). Hasta donde yo sé, un día se define como 24 horas, y cualquier "variación" en eso debido al horario de verano es en realidad un cambio de zonas horarias. Si todavía no distingue entre zonas horarias, tratar de descubrir una diferencia horaria lo colocará en un mundo de dolor, sobre todo porque el cambio de horario de verano 'repite' el tiempo. Sin embargo, quédese en una zona horaria y todo funciona.
icktoofay
12
@ trisweb: incluso algo tan simple como obtener una diferencia en días es más complejo que tu comentario. ¿Cuántos días entre las 10 p. M. Martes y las 9 a. M. Miércoles? Su algoritmo dice 0. Otros podrían pensar 1.
RobG
Los relativistas de @RobG podrían incluso pensar más de 1 o menos de 0. Todo depende del observador.
Inocente espectador
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));

Muestra de código tomada de aquí .

Paresh Mayani
fuente
Esto solo devuelve la diferencia de fecha en el formato dado si se usa como un solo contador. Por ejemplo, si desea 3 meses, 4 días y 5 horas, NO producirá esos resultados. Más en la línea de 3 meses 96 días y muchas horas.
Joris Kroos
30

Otra solución es convertir la diferencia en un nuevo objeto Fecha y obtener el año de esa fecha (diferente de 1970), mes, día, etc.

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

Entonces la diferencia es como "3 años y 6 meses y 4 días". Si quieres tomar la diferencia en un estilo legible para humanos, eso puede ayudarte.

Murat Çorlu
fuente
¡No es el significado! ¡Queremos TODA la diferencia! En este ejemplo, ¡la diferencia en días es 1281, no 4!
chaim.dev
3
@ chaim.dev "Si quieres tomar la diferencia en un estilo legible por humanos, eso puede ayudarte".
Murat Çorlu
77
Esto no es confiable. No tiene en cuenta la duración variable de los meses o los años bisiestos y otras anomalías.
Marc Durdin
2
Gracias Murat, esta solución ha resuelto mi problema. Lo que realmente quiero es que debe funcionar de la misma manera que lo hace php.
Ritesh Patadiya
27

Expresiones como "diferencia en días" nunca son tan simples como parecen. Si tienes las siguientes fechas:

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

la diferencia en el tiempo es de 2 minutos, ¿la "diferencia en días" debería ser 1 o 0? Surgen problemas similares para cualquier expresión de la diferencia en meses, años o lo que sea, ya que los años, meses y días son de diferentes duraciones y diferentes tiempos (por ejemplo, el día en que comienza el horario de verano es 1 hora más corto de lo habitual y dos horas menos que el día en que termina).

Aquí hay una función para una diferencia en días que ignora la hora, es decir, para las fechas anteriores, devuelve 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 );
}

Esto puede ser más 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>');
});

RobG
fuente
1
@ rudeovskizebear: probado en IE, Firefox y Safari, funciona bien. Utiliza ECMAScript básico que esperaría que funcione en cualquier navegador, ¿qué no funciona para usted?
RobG
Lo puse en una página de prueba, y funcionó bien en Chrome, pero seguí volviendo nulo en IE9 y el último FF
mnsr
@ RafiB. — No sé cómo cree que uno es más preciso que el otro, hacen esencialmente lo mismo, es decir, calculan la diferencia en días enteros utilizando un valor de hora UTC. La ambigüedad en la pregunta no fue aclarada. Si lo fuera, puede conducir a una solución diferente.
RobG
@RobG Edite los ejemplos en los comentarios de una solución más concisa. El mes debe ser '12' no '22'
S.aad
1
@ IgorKudryashov: lo siento, simplemente no lo entiendo. 2000 es un año bisiesto, de modo que del 28 de febrero de 2000 al 28 de febrero de 2001 son 366 días. En un año no bisiesto, son 365 días. He agregado algunos ejemplos más.
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
fuente
No me ayuda No se puede extender esto a meses o años con el mismo enfoque.
tomazahlin
9

use Moment.js para todos sus cálculos de fecha y hora relacionados con JavaScript

La respuesta a su pregunta es:

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

Los detalles completos se pueden encontrar aquí

Basant Sahu
fuente
44
Y aproveche los más de 400 Kb adicionales para una simple diferencia de fecha.
Romeo Mihalcea
@RomeoMihalcea Minified current.js 2.22.2 con una configuración regional es de 53 KB, 17 KB comprimidos. Aunque entiendo tu preocupación. Es una gran biblioteca para usar para una función simple, pero se ocupa de tantas peculiaridades relacionadas con la fecha / hora que a menudo 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      
}
usuario2513608
fuente
Gracias por las soluciones :)
bhagirathi
La mayoría de las soluciones que encontré no funcionan o son demasiado largas. ¡Su solución es la más simple hasta ahora y funciona exactamente como se esperaba! Saludos :)
Bruce
¿Qué pasa si quiero saber la diferencia con más precisión de una hora? en la pregunta posterior hay horas y segundos, ¿qué pasa con todos estos ajustes de ceros?
2oppin
8

Con momentjs es simple:

moment("2016-04-08").fromNow();
Josh LaMar
fuente
1
moment.js es genial! :)
Kami
Buena respuesta, pero probablemente exagere para esta situación específica.
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.
fuente
4

Lo sentimos, pero el cálculo plano de milisegundos no es confiable Gracias por todas las respuestas, pero pocas de las funciones que probé fallan en 1. Una fecha cercana a la fecha de hoy 2. Una fecha en 1970 o 3. Una fecha en un año bisiesto.

Enfoque que mejor funcionó para mí y cubre todos los escenarios, por ejemplo, año bisiesto, fecha próxima en 1970, 29 de febrero, etc.

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
fuente
3

Si está utilizando moment.js, entonces es bastante sencillo encontrar la diferencia de fecha.

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
fuente
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
fuente
3

Creo que esto debería hacerlo.

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
fuente
2

Así es como puede implementar la diferencia entre fechas sin un marco.

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
fuente
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
fuente
Este código proporciona resultados precisos sobre el número de días, tiempo e incluso minutos
Maximus Su
Espero que lo estén usando
Maximus Su
0

Ok, hay muchas formas de hacerlo. Sí, puedes usar JS viejo y simple. Sólo inténtalo:

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

Emulemos el pasaje usando Date.prototype.setMinutes y asegurémonos de que estamos dentro del rango.

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

Alternativamente, podría usar alguna biblioteca como js-joda , donde puede hacer fácilmente cosas como esta (directamente desde documentos):

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

Hay muchas más bibliotecas ofc, pero js-joda tiene una ventaja adicional de estar disponible también en Java, donde se ha probado exhaustivamente. Todas esas pruebas se han migrado a js-joda, también es inmutable.

mwojtera
fuente
-1

esto debería funcionar bien si solo necesita mostrar el tiempo restante, ya que JavaScript usa marcos para su tiempo, obtendrá su Hora de finalización: el tiempo RN después de eso podemos dividirlo por 1000, ya que aparentemente 1000 marcos = 1 segundo, después de eso, puede usar las matemáticas básicas del tiempo, pero todavía hay un problema con este código, ya que el cálculo es estático, no puede compensar el total de días diferentes en un año (360/365/366), el montón de SI después de que el cálculo sea nulo si el tiempo es inferior a 0, espero que esto ayude aunque no sea exactamente lo que está preguntando :)

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
fuente