Como obter a diferença de duas datas no formato mm-dd-hh em JavaScript

Eu posso conseguir a diferença entre duas datas usando moment.js ou plain js.

em moment.js

var a = moment(timestamp1); var b = moment(timestamp2); var month =a.diff(b, 'month'); var day =a.diff(b, 'day') - month; var year =a.diff(b, 'hours'); 

mês retorna mês, dias retorno diferença em dias. Mas eu quero a resposta em

Formato MM-DD-hh por exemplo 2 meses 12 dias 5 horas. Não consigo converter o dia diretamente porque há outros problemas como ano bissexto. Existe alguma outra maneira, depois de tudo sair e calcular tudo? Eu estou fazendo isso em js angular se isso é de alguma ajuda

Obter a diferença precisa entre duas datas não é simples, pois anos, meses e dias têm comprimentos diferentes. Além disso, adicionar não é necessariamente simétrico com subtração, por exemplo, 30 de abril, mais um mês é 30 de maio, mas é 31 de maio, mais um mês de 30 de junho ou 1 de julho? Semelhante a 29 de fevereiro, mais ou menos 1 ano.

O seguinte tenta lidar com esses problemas, de modo que, se adicionar um mês acumular um mês a mais, a data será retornada para o último dia do mês anterior. Espero que os comentários sejam suficientes, se não, peça esclarecimentos.

A function dateDiff retorna uma matriz dos valores para anos, meses, dias, etc. Para obter o MM-DD-hh, é só pegar isso e formatá-lo como quiser. Eu incluí uma pequena function de formatação que apenas imprime os componentes não-zero.

 // Simple calculation of days between two dates based on time value function getDaysDiff(start, end) { return ((parseStringUTC(end) - parseStringUTC(start))/8.64e7).toFixed(2); } // Expects input in ISO8601 format: yyyy-mm-ddThh:mm:ss.sssZ // Always expects UTC function parseStringUTC(s) { s = s.split(/\D/); s[6] = s[6]? ('0.'+ s[6]) * 1000 : 0; return new Date(Date.UTC(s[0],--s[1],s[2],s[3]||0,s[4]||0,s[5]||0,s[6]||0)); } /* Get the difference between two dates in years, months, days, ** hours, minutes and seconds. ** ** Difference is values to add to earlier date to reach later date. ** ** Does not consider daylight saving changes so may be incorrect by offset ** difference over daylight saving boundaries, so use UTC values (pass ** values as date.toISOString() or format like ISO 8601 UTC) ** ** @param {string} d0 - earlier date in format ymd h:m:s, can also be ** yyyy-mm-ddThh:mm:ssZ, the timezone offset is ignored ** the string is not validated ** @param {string} d1 - later date in same format as above. If d1 is earlier ** than d0, results are unreliable. ** @returns {Array} values for years, months, days, hours, minutes and ** seconds (milliseconds as decimal part of seconds) */ function dateDiff(d0,d1) { var s = d0.split(/\D/); var e = d1.split(/\D/); // Calculate initial values for components, // Time component is optional, missing values treated as zero var ms = (e[6]||0) - (s[6]||0); var sec = (e[5]||0) - (s[5]||0); var min = (e[4]||0) - (s[4]||0); var hr = (e[3]||0) - (s[3]||0); var day = e[2] - s[2]; var mon = e[1] - s[1]; var yr = e[0] - s[0]; // Borrowing to resolve -ve values. if (ms < 0) { // ms borrow from sec ms += 1000; --sec; } if (sec < 0) { // sec borrows from min sec += 60; --min; } if (min < 0) { // min borrows from hr min += 60; --hr; } if (hr < 0) { // hr borrows from day hr += 24; --day; } // Day borrows from month, a little complex but not too hard if (day < 0) { var prevMonLen = new Date(e[0], e[1]-1, 0).getDate(); // If the start date is less than the number of days in the previous month, // set days to previous month length + current diff days value // Note that current diff days may have had a day borrowed, so don't use end date - start date // Otherwise, if the start date is equal to or greater than the number of // days in the previous month, just set to end date. That's because adding // 1 month to 30 Jan should be last day in Feb (ie 28 or 29), not 2 or 1 March // respectively, which is what happens if adding 1 month to a Date object for 30 Jan. // Similarly, 31 May + 1 month should be 30 June, not 1 July. day = s[2] < prevMonLen? prevMonLen + day : +e[2]; --mon; } if (mon < 0) { // mon borrows from yr mon += 12; --yr; } // If days >= number of days in end month and end date is last day // of month, zero mon and add one to month // If then months = 12, zero and add one to years var endMonLen = new Date(e[0], e[1], 0).getDate(); if (day >= endMonLen && s[2] > e[2] && e[2] == endMonLen) { day = 0; ++mon; if (mon == 12) { mon = 0; ++yr; } } return [yr,mon,day,hr,min,+(sec + '.' + ('00'+ms).slice(-3))]; } /* Format output from dateDiff function, eg 3years, 2 days, 23.12 seconds ** ** @param {Array} v - values array in order years, months, days, hours, minutes ** seconds (milliseconds as decimal part of seconds) ** @returns {string} Values with their names appended. Adds "s" to values other ** than 1, zero values omitted, eg "0 months" not returned. */ function formatOutput(v) { var values = ['year','month','day','hour','minute','second'] return v.reduce(function (s, x, i) { s += x? (s.length? ' ' : '') + (i == 5? x.toFixed(3) : x) + ' ' + values[i] + (x==1?'':'s'):''; return s; }, ''); } // Tests, focus on February var dates = [ ['2016-01-31','2016-03-01'], // 1 month 1 day - 31 Jan + 1 month = 29 Feb ['2016-01-29','2016-03-01'], // 1 month 1 day - 29 Jan + 1 month = 29 Feb ['2016-01-27','2016-03-01'], // 1 month 3 days - 27 Jan + 1 month = 27 Feb ['2016-01-27','2016-03-29'], // 2 months 2 days - 27 Jan + 2 month = 27 Mar ['2016-01-29','2016-03-27'], // 1 month 27 days - 29 Jan + 1 month = 29 Feb ['2015-12-31','2016-01-30'], // 30 days - 31 Dec + 30 days = 30 Jan ['2015-12-27','2016-01-30'], // 1 month 3 days - 27 Dec + 1 month = 27 Jan ['2016-02-29','2017-02-28'], // 1 year could also be 11 months 30 days // since 29 Feb + 11 months = 28 Feb, but 28 Feb is last day of month // so roll over to full year // Both work, but 1 year is more logical ['1957-12-04','2016-02-20'], // 58 years 2 months 16 days ['2000-02-29','2016-02-28'], // 15 years 11 months 30 days // Not full year as Feb 2016 has 29 days ['2000-02-28','2016-02-28'], // 16 years ['2000-02-28','2016-02-29'], // 16 years 1 day ['2016-02-28T23:52:19.212Z','2016-12-02T01:48:57.102Z'] // 9 months 3 days 1 hour 56 minutes 37.899 seconds ]; var arr = []; dates.forEach(function(a) { arr.push(a[0] + ' to ' + a[1] + '
' + formatOutput(dateDiff(a[0], a[1]))); }); document.write(arr.join('
'));
  table { border-collapse:collapse; border-left: 1px solid #bbbbbb; border-top: 1px solid #bbbbbb; } input { width: 12em; } input.bigGuy { width: 32em; } td { border-right: 1px solid #bbbbbb; border-bottom: 1px solid #bbbbbb; } td:nth-child(1) { text-align: right; } 
 
  var date1 = new Date("4/14/2016"); var date2 = new Date("10/16/2016"); var timeDiff = Math.abs(date2.getTime() - date1.getTime()); var newDate = new Date(timeDiff); alert(newDate); alert("Month " + (newDate.getUTCMonth() + 1)); alert("Date " + newDate.getUTCDate()); alert("Hour " + newDate.getUTCHours()); 

você não pode converter uma diferença (resultado diff é um número) para o formato MM-DD-hh, porque alguns meses são 30 dias, os outros têm 31 dias.

Pode ser calculado a partir do início e do término da data e hora.

Há uma function semelhante à que você está procurando, mas não exata

 moment("2010-01-01").from("2010-12-01") 

Resultado: um ano atrás

 moment("2010-01-01").from("2010-12-01", true) 

Resultado: um ano