Cómo obtener la diferencia de dos fechas en formato mm-dd-hh en Javascript

Puedo obtener la diferencia entre dos fechas usando moment.js o js simples.

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

mes regresa mes, días devuelve diferencia en días. Pero quiero la respuesta en

Formato MM-DD-hh, por ejemplo, 2 meses, 12 días y 5 horas. No puedo convertir el día directamente porque hay otros problemas, como el año bisiesto. ¿Hay alguna otra manera que salir todo y calcular todo? Estoy haciendo esto en angular js si eso es de alguna ayuda

Obtener la diferencia precisa entre dos fechas no es simple ya que los años, meses y días tienen diferentes longitudes. Además, agregar no es necesariamente simétrico con resta, por ejemplo, es 30 de abril más un mes es 30 de mayo, pero es 31 de mayo más un mes 30 de junio o 1 de julio? Similar con 29 fe más o menos 1 año.

A continuación, se trata de resolver estos problemas, de modo que si agrega un mes durante un mes adicional, la fecha se devuelve al último día del mes anterior. Esperemos que los comentarios sean suficientes, si no, solicite una aclaración.

La función dateDiff devuelve una matriz de valores por años, meses, días, etc. Para obtener MM-DD-hh, solo tiene que obtener eso y formatearlo de la forma que desee. He incluido una función de formato pequeño que simplemente imprime los componentes distintos de cero.

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

no puede convertir una diferencia (el resultado de diff es un número) en formato MM-DD-hh, porque algunos meses tienen una duración de 30 días, los demás tienen una duración de 31 días.

Se puede calcular a partir de la fecha de inicio y finalización.

Hay una función similar a la que está buscando, pero no es exacta

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

resultado: hace un año

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

resultado: un año