55 votos

Diferencia de meses entre dos fechas en JavaScript

¿Cómo podría calcular la diferencia de dos objetos Date() en JavaScript, y al mismo tiempo devolver el número de meses de la diferencia?

Cualquier ayuda sería genial :)

106voto

T.J. Crowder Puntos 285826

La definición de "número de meses de diferencia" está sujeta a muchas interpretaciones. :-)

Puede obtener el año, el mes y el día del mes de un objeto de fecha de JavaScript. Dependiendo de la información que busques, puedes usarlos para averiguar cuántos meses hay entre dos puntos en el tiempo.

Por ejemplo, de improviso:

function monthDiff(d1, d2) {
    var months;
    months = (d2.getFullYear() - d1.getFullYear()) * 12;
    months -= d1.getMonth();
    months += d2.getMonth();
    return months <= 0 ? 0 : months;
}

function monthDiff(d1, d2) {
    var months;
    months = (d2.getFullYear() - d1.getFullYear()) * 12;
    months -= d1.getMonth();
    months += d2.getMonth();
    return months <= 0 ? 0 : months;
}

function test(d1, d2) {
    var diff = monthDiff(d1, d2);
    console.log(
        d1.toISOString().substring(0, 10),
        "to",
        d2.toISOString().substring(0, 10),
        ":",
        diff
    );
}

test(
    new Date(2008, 10, 4), // November 4th, 2008
    new Date(2010, 2, 12)  // March 12th, 2010
);
// Result: 16

test(
    new Date(2010, 0, 1),  // January 1st, 2010
    new Date(2010, 2, 12)  // March 12th, 2010
);
// Result: 2

test(
    new Date(2010, 1, 1),  // February 1st, 2010
    new Date(2010, 2, 12)  // March 12th, 2010
);
// Result: 1

(Tenga en cuenta que los valores de los meses en JavaScript empiezan por 0 = enero).

Incluir los meses fraccionarios en lo anterior es mucho más complicado, porque tres días en un febrero típico es una fracción mayor de ese mes (~10,714%) que tres días en agosto (~9,677%), y por supuesto incluso febrero es un objetivo móvil dependiendo de si es un año bisiesto.

También hay algunos bibliotecas de fecha y hora disponibles para JavaScript que probablemente faciliten este tipo de cosas.


Nota : Solía haber un + 1 en lo anterior, aquí:

months = (d2.getFullYear() - d1.getFullYear()) * 12;
months -= d1.getMonth() + 1;
// −−−−−−−−−−−−−−−−−−−−^^^^
months += d2.getMonth();

Eso es porque originalmente dije:

...esto descubre cuántos meses completos se encuentran entre dos fechas, sin contar los meses parciales (por ejemplo, excluyendo el mes en el que se encuentra cada fecha).

Lo he eliminado por dos razones:

  1. No contar los meses parciales resulta no ser lo que muchos (¿la mayoría?) de las personas que acuden a la respuesta quieren, así que pensé que debía separarlos.

  2. No siempre funcionó ni siquiera con esa definición. :-D (Lo siento.)

30voto

Tom Gullen Puntos 20826

Si no se tiene en cuenta el día del mes, ésta es, con mucho, la solución más sencilla

function monthDiff(dateFrom, dateTo) {
 return dateTo.getMonth() - dateFrom.getMonth() + 
   (12 * (dateTo.getFullYear() - dateFrom.getFullYear()))
}

//examples
console.log(monthDiff(new Date(2000, 01), new Date(2000, 02))) // 1
console.log(monthDiff(new Date(1999, 02), new Date(2000, 02))) // 12 full year
console.log(monthDiff(new Date(2009, 11), new Date(2010, 0))) // 1

Tenga en cuenta que el índice del mes se basa en el 0. Esto significa que January = 0 y December = 11 .

12voto

Mike JM Puntos 3895

A veces puede querer obtener sólo la cantidad de meses entre dos fechas ignorando totalmente la parte del día. Así, por ejemplo, si tienes dos fechas - 2013/06/21 y 2013/10/18- y sólo te importan las partes 2013/06 y 2013/10, aquí están los escenarios y las posibles soluciones:

var date1=new Date(2013,5,21);//Remember, months are 0 based in JS
var date2=new Date(2013,9,18);
var year1=date1.getFullYear();
var year2=date2.getFullYear();
var month1=date1.getMonth();
var month2=date2.getMonth();
if(month1===0){ //Have to take into account
  month1++;
  month2++;
}
var numberOfMonths; 

1.Si quieres sólo el número de los meses entre las dos fechas excluyendo tanto el mes1 como el mes2

numberOfMonths = (year2 - year1) * 12 + (month2 - month1) - 1;

2.Si quiere incluir alguno de los meses

numberOfMonths = (year2 - year1) * 12 + (month2 - month1);

3.Si quieres incluir los dos meses

numberOfMonths = (year2 - year1) * 12 + (month2 - month1) + 1;

6voto

harun Puntos 798

Si necesita contar meses completos, independientemente de que el mes tenga 28, 29, 30 o 31 días. Lo siguiente debería funcionar.

var months = to.getMonth() - from.getMonth() 
    + (12 * (to.getFullYear() - from.getFullYear()));

if(to.getDate() < from.getDate()){
    months--;
}
return months;

Esta es una versión ampliada de la respuesta https://stackoverflow.com/a/4312956/1987208 pero arregla el caso en el que calcula 1 mes para el caso del 31 de enero al 1 de febrero (1 día).

Esto cubrirá lo siguiente;

  • Del 1 de enero al 31 de enero ---> 30 días ---> dará como resultado 0 (lógico ya que no es un mes completo)
  • Del 1 de febrero al 1 de marzo ---> 28 o 29 días ---> dará como resultado 1 (lógico ya que es un mes completo)
  • Del 15 de febrero al 15 de marzo ---> 28 o 29 días ---> resultará 1 (lógico ya que pasó un mes)
  • Del 31 de enero al 1 de febrero ---> 1 día ---> resultará en 0 (obvio pero la respuesta mencionada en el post resulta en 1 mes)

2voto

calvin Puntos 412

Para ampliar la respuesta de @T.J., si lo que buscas son meses simples, en lugar de meses naturales completos, podrías simplemente comprobar si la fecha de d2 es mayor o igual que la de d1. Es decir, si d2 es más tarde en su mes que d1 en su mes, entonces hay 1 mes más. Así que deberías poder hacer esto:

function monthDiff(d1, d2) {
    var months;
    months = (d2.getFullYear() - d1.getFullYear()) * 12;
    months -= d1.getMonth() + 1;
    months += d2.getMonth();
    // edit: increment months if d2 comes later in its month than d1 in its month
    if (d2.getDate() >= d1.getDate())
        months++
    // end edit
    return months <= 0 ? 0 : months;
}

monthDiff(
    new Date(2008, 10, 4), // November 4th, 2008
    new Date(2010, 2, 12)  // March 12th, 2010
);
// Result: 16; 4 Nov – 4 Dec '08, 4 Dec '08 – 4 Dec '09, 4 Dec '09 – 4 March '10

Esto no tiene en cuenta totalmente los problemas de tiempo (por ejemplo, el 3 de marzo a las 16:00 y el 3 de abril a las 15:00), pero es más preciso y por sólo un par de líneas de código.

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X