¿Cómo resolvería la diferencia para dos objetos Date () en JavaScript, mientras solo devuelvo el número de meses en la diferencia?
Cualquier ayuda sería genial :)
¿Cómo resolvería la diferencia para dos objetos Date () en JavaScript, mientras solo devuelvo el número de meses en la diferencia?
Cualquier ayuda sería genial :)
Respuestas:
La definición de "el número de meses en la diferencia" está sujeta a mucha interpretación. :-)
Puede obtener el año, mes y día del mes a partir de un objeto de fecha de JavaScript. Dependiendo de la información que esté buscando, puede usarlos para calcular cuántos meses hay entre dos puntos en el tiempo.
Por ejemplo, fuera de lugar:
function monthDiff(d1, d2) {
var months;
months = (d2.getFullYear() - d1.getFullYear()) * 12;
months -= d1.getMonth();
months += d2.getMonth();
return months <= 0 ? 0 : months;
}
(Tenga en cuenta que los valores de mes en JavaScript comienzan con 0 = enero).
Incluir 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 algunas 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 hay entre dos fechas, sin contar los meses parciales (por ejemplo, excluyendo el mes en que se encuentra cada fecha).
Lo he eliminado por dos razones:
Sin contar los meses parciales resulta que no es lo que quieren (¿la mayoría?) Las personas que llegan a la respuesta, así que pensé que debería separarlos.
No siempre funcionó incluso con esa definición. :-D (lo siento)
Si no considera el día del mes, esta es la solución más simple.
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 mensual está basado en 0. Esto significa que January = 0
y December = 11
.
A veces es posible que desee obtener solo la cantidad de meses entre dos fechas ignorando totalmente la parte del día. Entonces, por ejemplo, si tuvo dos fechas: 2013/06/21 y 2013/10 / 18- y solo le importaron las partes 2013/06 y 2013/10, estos son 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 desea solo el número de meses entre las dos fechas, excluyendo ambos mes1 y mes2
numberOfMonths = (year2 - year1) * 12 + (month2 - month1) - 1;
2.Si quieres 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;
numberOfMonths=(year2-year1)*12+(month2-month1)+1;
que hace lo mismo pero es más semánticamente correcto para mí
Aquí hay una función que proporciona con precisión el número de meses entre 2 fechas.
El comportamiento predeterminado solo cuenta meses completos, por ejemplo, 3 meses y 1 día dará como resultado una diferencia de 3 meses. Puede evitar esto configurando el parámetro roundUpFractionalMonths
como true
, por lo que una diferencia de 3 meses y 1 día se devolverá como 4 meses.
La respuesta aceptada arriba (respuesta de TJ Crowder) no es precisa, a veces devuelve valores incorrectos.
Por ejemplo, monthDiff(new Date('Jul 01, 2015'), new Date('Aug 05, 2015'))
devuelve0
que obviamente es incorrecto. La diferencia correcta es 1 mes completo o 2 meses redondeados.
Aquí está la función que escribí:
function getMonthsBetween(date1,date2,roundUpFractionalMonths)
{
//Months will be calculated between start and end dates.
//Make sure start date is less than end date.
//But remember if the difference should be negative.
var startDate=date1;
var endDate=date2;
var inverse=false;
if(date1>date2)
{
startDate=date2;
endDate=date1;
inverse=true;
}
//Calculate the differences between the start and end dates
var yearsDifference=endDate.getFullYear()-startDate.getFullYear();
var monthsDifference=endDate.getMonth()-startDate.getMonth();
var daysDifference=endDate.getDate()-startDate.getDate();
var monthCorrection=0;
//If roundUpFractionalMonths is true, check if an extra month needs to be added from rounding up.
//The difference is done by ceiling (round up), e.g. 3 months and 1 day will be 4 months.
if(roundUpFractionalMonths===true && daysDifference>0)
{
monthCorrection=1;
}
//If the day difference between the 2 months is negative, the last month is not a whole month.
else if(roundUpFractionalMonths!==true && daysDifference<0)
{
monthCorrection=-1;
}
return (inverse?-1:1)*(yearsDifference*12+monthsDifference+monthCorrection);
};
Si necesita contar meses completos, independientemente de que el mes sea 28, 29, 30 o 31 días. A continuación 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 extendida de la respuesta https://stackoverflow.com/a/4312956/1987208, pero corrige 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;
Diferencia en meses entre dos fechas en JavaScript:
start_date = new Date(year, month, day); //Create start date object by passing appropiate argument
end_date = new Date(new Date(year, month, day)
meses totales entre fecha_inicio y fecha_finalización:
total_months = (end_date.getFullYear() - start_date.getFullYear())*12 + (end_date.getMonth() - start_date.getMonth())
Sé que esto es muy tarde, pero publicarlo de todos modos en caso de que ayude a otros. Aquí hay una función que se me ocurrió que parece hacer un buen trabajo al contar las diferencias en meses entre dos fechas. Es cierto que es mucho más atrevido que Mr.Crowder, pero proporciona resultados más precisos al pasar por el objeto de fecha. Está en AS3, pero debería poder soltar la escritura fuerte y tendrá JS. ¡Siéntase libre de hacer que se vea mejor a cualquiera!
function countMonths ( startDate:Date, endDate:Date ):int
{
var stepDate:Date = new Date;
stepDate.time = startDate.time;
var monthCount:int;
while( stepDate.time <= endDate.time ) {
stepDate.month += 1;
monthCount += 1;
}
if ( stepDate != endDate ) {
monthCount -= 1;
}
return monthCount;
}
Para ampliar la respuesta de @ TJ, si está buscando meses simples, en lugar de meses calendario completos, puede verificar si la fecha de d2 es mayor o igual que d1. Es decir, si d2 es más tarde en su mes que d1 en su mes, entonces hay 1 mes más. Entonces 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 los problemas de tiempo (por ejemplo, el 3 de marzo a las 4:00 p.m. y el 3 de abril a las 3:00 p.m.), pero es más preciso y solo tiene un par de líneas de código.
Considere cada fecha en términos de meses, luego reste para encontrar la diferencia.
var past_date = new Date('11/1/2014');
var current_date = new Date();
var difference = (current_date.getFullYear()*12 + current_date.getMonth()) - (past_date.getFullYear()*12 + past_date.getMonth());
Esto le dará la diferencia de meses entre las dos fechas, ignorando los días.
Hay dos enfoques, matemático y rápido, pero sujeto a caprichos en el calendario, o iterativo y lento, pero maneja todas las rarezas (o al menos los delegados las manejan en una biblioteca bien probada).
Si itera por el calendario, incremente la fecha de inicio en un mes y vea si pasamos la fecha de finalización. Esto delega el manejo de anomalías a las clases integradas Date (), pero podría ser lento SI está haciendo esto por un gran número de fechas. La respuesta de James toma este enfoque. Por mucho que no me guste la idea, creo que este es el enfoque "más seguro", y si solo está haciendo un cálculo, la diferencia de rendimiento es realmente insignificante. Tendemos a tratar de optimizar las tareas que solo se realizarán una vez.
Ahora, si está calculando esta función en un conjunto de datos, probablemente no quiera ejecutar esa función en cada fila (o Dios no lo quiera, varias veces por registro). En ese caso, puede usar casi cualquiera de las otras respuestas aquí excepto la respuesta aceptada, que es simplemente incorrecta (la diferencia entre new Date()
y new Date()
es -1).
Aquí está mi apuesta por un enfoque matemático y rápido, que representa diferentes duraciones de meses y años bisiestos. Realmente solo debería usar una función como esta si la aplicará a un conjunto de datos (haciendo este cálculo una y otra vez). Si solo necesita hacerlo una vez, use el enfoque iterativo de James anterior, ya que está delegando el manejo de todas las (muchas) excepciones al objeto Date ().
function diffInMonths(from, to){
var months = to.getMonth() - from.getMonth() + (12 * (to.getFullYear() - from.getFullYear()));
if(to.getDate() < from.getDate()){
var newFrom = new Date(to.getFullYear(),to.getMonth(),from.getDate());
if (to < newFrom && to.getMonth() == newFrom.getMonth() && to.getYear() %4 != 0){
months--;
}
}
return months;
}
Aquí tienes otro enfoque con menos bucles:
calculateTotalMonthsDifference = function(firstDate, secondDate) {
var fm = firstDate.getMonth();
var fy = firstDate.getFullYear();
var sm = secondDate.getMonth();
var sy = secondDate.getFullYear();
var months = Math.abs(((fy - sy) * 12) + fm - sm);
var firstBefore = firstDate > secondDate;
firstDate.setFullYear(sy);
firstDate.setMonth(sm);
firstBefore ? firstDate < secondDate ? months-- : "" : secondDate < firstDate ? months-- : "";
return months;
}
También podría considerar esta solución, esto function
devuelve la diferencia mensual en número entero o número
Pasar la fecha de inicio como la primera o la última param
es tolerante a fallas. Es decir, la función aún devolvería el mismo valor.
const diffInMonths = (end, start) => {
var timeDiff = Math.abs(end.getTime() - start.getTime());
return Math.round(timeDiff / (2e3 * 3600 * 365.25));
}
const result = diffInMonths(new Date(2015, 3, 28), new Date(2010, 1, 25));
// shows month difference as integer/number
console.log(result);
Calcular la diferencia entre dos fechas incluye fracción de mes (días).
var difference = (date2.getDate() - date1.getDate()) / 30 +
date2.getMonth() - date1.getMonth() +
(12 * (date2.getFullYear() - date1.getFullYear()));
Por ejemplo:
fecha1 : 24/09/2015 (24 de septiembre de 2015)
fecha2 : 11/09/2015 (9 de noviembre de 2015)
la diferencia: 2.5 (meses)
Esto debería funcionar bien:
function monthDiff(d1, d2) {
var months;
months = (d2.getFullYear() - d1.getFullYear()) * 12;
months += d2.getMonth() - d1.getMonth();
return months;
}
function calcualteMonthYr(){
var fromDate =new Date($('#txtDurationFrom2').val()); //date picker (text fields)
var toDate = new Date($('#txtDurationTo2').val());
var months=0;
months = (toDate.getFullYear() - fromDate.getFullYear()) * 12;
months -= fromDate.getMonth();
months += toDate.getMonth();
if (toDate.getDate() < fromDate.getDate()){
months--;
}
$('#txtTimePeriod2').val(months);
}
El siguiente código devuelve meses completos entre dos fechas teniendo en cuenta también el número de días de meses parciales.
var monthDiff = function(d1, d2) {
if( d2 < d1 ) {
var dTmp = d2;
d2 = d1;
d1 = dTmp;
}
var months = (d2.getFullYear() - d1.getFullYear()) * 12;
months -= d1.getMonth() + 1;
months += d2.getMonth();
if( d1.getDate() <= d2.getDate() ) months += 1;
return months;
}
monthDiff(new Date(2015, 01, 20), new Date(2015, 02, 20))
> 1
monthDiff(new Date(2015, 01, 20), new Date(2015, 02, 19))
> 0
monthDiff(new Date(2015, 01, 20), new Date(2015, 01, 22))
> 0
function monthDiff(d1, d2) {
var months, d1day, d2day, d1new, d2new, diffdate,d2month,d2year,d1maxday,d2maxday;
months = (d2.getFullYear() - d1.getFullYear()) * 12;
months -= d1.getMonth() + 1;
months += d2.getMonth();
months = (months <= 0 ? 0 : months);
d1day = d1.getDate();
d2day = d2.getDate();
if(d1day > d2day)
{
d2month = d2.getMonth();
d2year = d2.getFullYear();
d1new = new Date(d2year, d2month-1, d1day,0,0,0,0);
var timeDiff = Math.abs(d2.getTime() - d1new.getTime());
diffdate = Math.abs(Math.ceil(timeDiff / (1000 * 3600 * 24)));
d1new = new Date(d2year, d2month, 1,0,0,0,0);
d1new.setDate(d1new.getDate()-1);
d1maxday = d1new.getDate();
months += diffdate / d1maxday;
}
else
{
if(!(d1.getMonth() == d2.getMonth() && d1.getFullYear() == d2.getFullYear()))
{
months += 1;
}
diffdate = d2day - d1day + 1;
d2month = d2.getMonth();
d2year = d2.getFullYear();
d2new = new Date(d2year, d2month + 1, 1, 0, 0, 0, 0);
d2new.setDate(d2new.getDate()-1);
d2maxday = d2new.getDate();
months += diffdate / d2maxday;
}
return months;
}
debajo de la lógica obtendrá la diferencia en meses
(endDate.getFullYear()*12+endDate.getMonth())-(startDate.getFullYear()*12+startDate.getMonth())
function monthDiff(date1, date2, countDays) {
countDays = (typeof countDays !== 'undefined') ? countDays : false;
if (!date1 || !date2) {
return 0;
}
let bigDate = date1;
let smallDate = date2;
if (date1 < date2) {
bigDate = date2;
smallDate = date1;
}
let monthsCount = (bigDate.getFullYear() - smallDate.getFullYear()) * 12 + (bigDate.getMonth() - smallDate.getMonth());
if (countDays && bigDate.getDate() < smallDate.getDate()) {
--monthsCount;
}
return monthsCount;
}
Mira lo que uso:
function monthDiff() {
var startdate = Date.parseExact($("#startingDate").val(), "dd/MM/yyyy");
var enddate = Date.parseExact($("#endingDate").val(), "dd/MM/yyyy");
var months = 0;
while (startdate < enddate) {
if (startdate.getMonth() === 1 && startdate.getDate() === 28) {
months++;
startdate.addMonths(1);
startdate.addDays(2);
} else {
months++;
startdate.addMonths(1);
}
}
return months;
}
También cuenta los días y los convierte en meses.
function monthDiff(d1, d2) {
var months;
months = (d2.getFullYear() - d1.getFullYear()) * 12; //calculates months between two years
months -= d1.getMonth() + 1;
months += d2.getMonth(); //calculates number of complete months between two months
day1 = 30-d1.getDate();
day2 = day1 + d2.getDate();
months += parseInt(day2/30); //calculates no of complete months lie between two dates
return months <= 0 ? 0 : months;
}
monthDiff(
new Date(2017, 8, 8), // Aug 8th, 2017 (d1)
new Date(2017, 12, 12) // Dec 12th, 2017 (d2)
);
//return value will be 4 months
En este caso, no me preocupan los meses completos, los meses parciales, la duración de un mes, etc. Solo necesito saber la cantidad de meses. Un caso relevante en el mundo real sería cuando se debe presentar un informe cada mes, y necesito saber cuántos informes debería haber.
Ejemplo:
Este es un ejemplo de código elaborado para mostrar a dónde van los números.
Tomemos 2 marcas de tiempo que deberían resultar en 4 meses
Puede ser ligeramente diferente con su zona horaria / hora extraída. El día, los minutos y los segundos no importan y pueden incluirse en la marca de tiempo, pero lo ignoraremos con nuestro cálculo real.
let dateRangeStartConverted = new Date(1573621200000);
let dateRangeEndConverted = new Date(1582261140000);
let startingMonth = dateRangeStartConverted.getMonth();
let startingYear = dateRangeStartConverted.getFullYear();
let endingMonth = dateRangeEndConverted.getMonth();
let endingYear = dateRangeEndConverted.getFullYear();
Esto nos da
(12 * (endYear - startYear)) + 1
al mes final.2 + (12 * (2020 - 2019)) + 1 = 15
15 - 11 = 4
; Obtenemos nuestro resultado de 4 meses.
Noviembre de 2019 hasta marzo de 2022 es de 29 meses. Si los coloca en una hoja de cálculo de Excel, verá 29 filas.
3 + (12 * (2022-2019)) + 1
40-11 = 29
anyVar = (((DisplayTo.getFullYear() * 12) + DisplayTo.getMonth()) - ((DisplayFrom.getFullYear() * 12) + DisplayFrom.getMonth()));
Un enfoque sería escribir un servicio web Java simple (REST / JSON) que use la biblioteca JODA
http://joda-time.sourceforge.net/faq.html#datediff
para calcular la diferencia entre dos fechas y llamar a ese servicio desde javascript.
Esto supone que su back-end está en Java.