Como calcular a diferença de data em JavaScript?

195

Quero calcular a diferença de data em dias, horas, minutos, segundos, milissegundos, nanossegundos. Como eu posso fazer isso?

Farhan Siddiqui
fonte
2
possível duplicata de Obter diferença entre 2 datas em javascript?
Anderson Green
1
As soluções abaixo não funcionarão se as duas datas envolvidas estiverem em fusos horários diferentes. Veja a pergunta em para uma solução mais precisa stackoverflow.com/questions/3224834/… ?
Shyam Habarakada

Respostas:

230

Supondo que você tenha dois Dateobjetos s, você pode simplesmente subtraí-los para obter a diferença em milissegundos:

var difference = date2 - date1;

A partir daí, você pode usar aritmética simples para derivar os outros valores.

icktoofay
fonte
41
Essa é a resposta certa. Ex: para obter a diferença em dias, faça Math.floor((date2 - date1) / (1000*60*60*24))- para a diferença em qualquer outra unidade, ajuste o denominador (o valor base está em ms).
trisweb de
36
Não existe uma aritmética "simples" para converter milissegundos em anos. Você deve estar atento ao ano bissexto, ao fuso horário, e alguns dias têm 23 ou 25 horas. Alguns anos têm 365,25 dias, então não há aritmética simples aqui (ainda procurando por uma solução precisa).
Alexandre Salomé
6
@Alexandre: Há anos a pergunta não é feita. Na verdade, calcular as diferenças anuais não é trivial. Para dias, no entanto, é correto, supondo que as datas estejam no mesmo fuso horário (uma suposição razoável). Pelo que eu sei, um dia é definido como 24 horas, e qualquer 'variação' devido ao horário de verão é na verdade uma mudança de fuso horário. Se você ainda não distingue os fusos horários, tentar descobrir uma diferença de tempo vai colocá-lo em um mundo de sofrimento, até porque a mudança de horário de verão "se repete". No entanto, fique em um fuso horário e tudo funcionará.
icktoofay
13
@trisweb — mesmo algo tão simples como obter a diferença de dias é mais complexo do que seu comentário. Quantos dias entre as 22h de terça e as 9h de quarta? Seu algoritmo diz 0. Outros podem pensar 1.
RobG
Os relativistas @RobG podem até pensar mais do que 1 ou menos do que 0. Tudo depende do observador.
Innocent Bystander
80
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));

Amostra de código retirada daqui .

Paresh Mayani
fonte
Isso só retorna a diferença de data no formato fornecido se usado como um único contador. Por exemplo, se você quiser 3 meses, 4 dias e 5 horas, NÃO produzirá esses resultados. Mais na linha de 3 meses 96 dias e muitas horas.
Joris Kroos
32

Outra solução é converter a diferença para um novo objeto Date e obter o ano dessa data (diff de 1970), mês, dia, 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

Portanto, a diferença é como "3 anos e 6 meses e 4 dias". Se você quiser entender a diferença em um estilo legível por humanos, isso pode ajudá-lo.

Murat Çorlu
fonte
Não é o significado! Queremos TODA a diferença! Neste exemplo, a diferença em dias é 1281, não 4!
chaim.dev
4
@ chaim.dev "Se você quiser entender a diferença em um estilo legível por humanos, isso pode ajudá-lo."
Murat Çorlu
8
Isso não é confiável. Ele não leva em consideração a variação da duração dos meses, ou anos bissextos e outras anomalias.
Marc Durdin
2
Obrigado Murat, Esta solução resolveu meu problema. O que eu realmente quero deve funcionar da mesma maneira que o php.
Ritesh Patadiya
27

Expressões como "diferença de dias" nunca são tão simples quanto parecem. Se você tem as seguintes datas:

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

a diferença de tempo é de 2 minutos, a "diferença em dias" deve ser 1 ou 0? Problemas semelhantes surgem para qualquer expressão da diferença em meses, anos ou qualquer outra coisa, já que anos, meses e dias são de durações e horários diferentes (por exemplo, o dia em que o horário de verão começa é 1 hora mais curto do que o normal e duas horas mais curto do que o dia que termina).

Aqui está uma função para uma diferença de dias que ignora a hora, ou seja, para as datas acima, retorna 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 );
}

Isso pode ser mais 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
fonte
1
@rudeovskizebear — testado no IE, Firefox e Safari, funciona bem. Ele usa ECMAScript básico que eu esperaria funcionar em qualquer navegador, o que não funciona para você?
RobG de
Eu o coloquei em uma página de teste e funcionou bem no Chrome, mas continuei recebendo null no IE9 e no último FF
mnsr
@ RafiB. — Não sei como você acha que um é mais preciso do que o outro, eles fazem essencialmente a mesma coisa, ou seja, calculam a diferença em dias inteiros usando um valor de hora UTC. A ambiguidade da questão não foi esclarecida. Se fosse, pode levar a uma solução diferente.
RobG de
@RobG Por favor, edite os exemplos nos comentários de uma solução mais concisa. O mês deve ser '12' e não '22'
S.aad
1
@IgorKudryashov — desculpe, não estou entendendo. 2000 é um ano bissexto, portanto, de 28 de fevereiro de 2000 a 28 de fevereiro de 2001 é de 366 dias. Em um ano não bissexto, são 365 dias. Eu adicionei mais alguns exemplos.
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
fonte
Não me ajuda. Não é possível estender isso para meses ou anos na mesma abordagem.
tomazahlin de
10

use Moment.js para todos os cálculos de data e hora relacionados ao JavaScript

A resposta à sua pergunta é:

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

Detalhes completos podem ser encontrados aqui

Basant Sahu
fonte
5
E adote os mais de 400 Kb extras para uma mera diferença de data.
Romeo Mihalcea
1
@RomeoMihalcea O moment.js minimizado atual 2.22.2 com um local é 53 KB, 17 KB compactado com gzip. Eu entendo sua preocupação. É uma enorme biblioteca para usar em uma função simples, mas cuida de tantas peculiaridades relacionadas a data / hora que geralmente vale a 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      
}
user2513608
fonte
Obrigado pelas soluções :)
bhagirathi
A maioria das soluções que encontrei não funciona ou é muito prolixa. Sua solução é a mais simples até agora e funciona exatamente como planejado! Saúde :)
Bruce,
e se eu quiser saber a diferença com mais precisão do que uma hora? no post pergunta há horas e segundos, o que para todos esses zerosettings?
2oppin
8

Com momentjs é simples:

moment("2016-04-08").fromNow();
Josh LaMar
fonte
1
moment.js é incrível! :)
Kami
Boa resposta, mas provavelmente um exagero para esta situação 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.
fonte
4

Desculpe, mas o cálculo fixo em milissegundos não é confiável. Obrigado por todas as respostas, mas algumas das funções que tentei falharam em 1. Uma data próxima à data de hoje 2. Uma data em 1970 ou 3. Uma data em um ano bissexto.

Abordagem que melhor funcionou para mim e cobre todos os cenários, por exemplo, ano bissexto, data próxima em 1970, 29 de fevereiro 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
fonte
4
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
fonte
O cenário abaixo resultará em valores inesperados [years, months, days] = DateDiff( new Date("October 21, 2019"), new Date("October 18, 2020")); // 1 -1 27 // 0 11 27 <- should be this... Para corrigir isso, adicione a (months < 0)condição novamente abaixo da linha demonths--;
Rivo
3

Se você estiver usando o moment.js, será muito simples encontrar a diferença de 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")
James Hawking
fonte
3

Eu acho que isso deve bastar.

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

É assim que você pode implementar a diferença entre datas sem uma estrutura.

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
fonte
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
fonte
Este código fornece resultados precisos sobre o número de dias, horas e até minutos
Maximus Su
Espero que vocês estejam usando
Maximus Su
1

com base na implementação de protótipo de tempo de execução javascript, você pode usar aritmética simples para subtrair datas como abaixo

var sep = new Date(2020, 07, 31, 23, 59, 59);
var today = new Date();
var diffD = Math.floor((sep - today) / (1000 * 60 * 60 * 24));
console.log('Day Diff: '+diffD);

a diferença retorna a resposta em milissegundos, então você deve convertê-la por divisão:

  • em 1000 para converter em segundo
  • por 1000 × 60 converter para minuto
  • por 1000 × 60 × 60 convertido em horas
  • por 1000 × 60 × 60 × 24 convertido em dia
Hamid Jolany
fonte
0

isso deve funcionar bem se você só precisa mostrar o tempo restante, já que o JavaScript usa frames para o seu tempo, você terá seu End Time - O tempo RN depois disso, podemos dividi-lo por 1000, pois aparentemente 1000 frames = 1 segundo, depois disso, você pode usar a matemática básica do tempo, mas ainda há um problema com este código, uma vez que o cálculo é estático, ele não pode compensar o total de dias diferentes em um ano (360/365/366), o monte de SE após o cálculo for torná-lo nulo se o tempo for inferior a 0, espero que isso ajude, embora não seja exatamente o que você está perguntando :)

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
fonte
0

Ok, existem várias maneiras de fazer isso. Sim, você pode usar o antigo JS. Apenas tente:

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

Vamos emular a passagem usando Date.prototype.setMinutes e ter certeza de que estamos dentro do alcance.

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

Como alternativa, você pode usar alguma biblioteca como js-joda , onde pode facilmente fazer coisas como esta (diretamente dos 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

Existem muitas outras bibliotecas ofc, mas js-joda tem um bônus adicional por estar disponível também em Java, onde foi amplamente testado. Todos esses testes foram migrados para js-joda, também é imutável.

mwojtera
fonte