¿Cómo calculo la fecha en JavaScript tres meses antes de hoy?

147

Estoy tratando de formar una fecha que sea 3 meses antes de la fecha actual. Obtengo el mes actual por el siguiente código

var currentDate = new Date();
var currentMonth = currentDate.getMonth()+1;

¿Pueden proporcionarme la lógica para calcular y formar una fecha (un objeto del Datetipo de datos) teniendo en cuenta que cuando el mes es enero (1), 3 meses antes de la fecha sería OCtober (10)?

KeenUser
fuente

Respuestas:

323
var d = new Date();
d.setMonth(d.getMonth() - 3);

Esto funciona para enero. Ejecute este fragmento:

var d = new Date("January 14, 2012");
console.log(d.toLocaleDateString());
d.setMonth(d.getMonth() - 3);
console.log(d.toLocaleDateString());


Hay algunas advertencias ...

Un mes es algo curioso. ¿Cómo se define 1 mes? ¿30 dias? La mayoría de la gente dirá que hace un mes significa el mismo día del mes en la cita del mes anterior necesaria . Pero más de la mitad del tiempo, es decir, hace 31 días, no 30. Y si hoy es el 31 del mes (y no es agosto o diciembre), ese día del mes no existe en el mes anterior.

Curiosamente, Google acepta JavaScript si le pregunta qué día es un mes antes de otro día :

El resultado de búsqueda de Google para 'un mes antes del 31 de marzo' muestra '3 de marzo'

También dice que un mes dura 30.4167 días : El resultado de búsqueda de Google para 'un mes en días' muestra '30 .4167 '

Entonces, ¿es un mes antes del 31 de marzo el mismo día que un mes antes del 28 de marzo, 3 días antes? Todo esto depende de lo que quiere decir con "un mes antes". Ve a conversar con el propietario de tu producto.

Si desea hacer lo que hace momentjs y corregir estos errores del último día del mes moviéndose al último día del mes, puede hacer algo como esto:

const d = new Date("March 31, 2019");
console.log(d.toLocaleDateString());
const month = d.getMonth();
d.setMonth(d.getMonth() - 1);
while (d.getMonth() === month) {
    d.setDate(d.getDate() - 1);
}
console.log(d.toLocaleDateString());

Si sus requisitos son más complicados que eso, use algunas matemáticas y escriba un código. Eres un desarrollador! ¡No tienes que instalar una biblioteca! ¡No tiene que copiar y pegar desde stackoverflow! ¡Puede desarrollar el código usted mismo para hacer exactamente lo que necesita!

gilly3
fuente
var currentDate = new Date (); var currentMonth = currentDate.getMonth () -12; var pastDate = new Date (2011, currentMonth, 01); alerta (pastDate); esto funcionó, verificado con 12 meses
KeenUser
Esta es una respuesta enferma ... ¿De dónde voy a obtener 2012,0,15? Convertir un mes existente -1?
Alex G
3
@AlexG: si eres nuevo en el análisis de fechas de JavaScript, entonces puedo ver cómo mi ejemplo rápido sería confuso. JavaScript expresa meses como cero basado, donde enero es cero. Para evitar tal confusión, especialmente porque eso no tiene nada que ver con la pregunta o mi respuesta, actualicé mi demo para obtener la fecha de una cadena, lo que debería ser más intuitivo.
gilly3
77
Sé que esto es antiguo, pero si la fecha es el 31 de marzo y restas un mes usando este método, el resultado es el 2 de marzo. jsfiddle.net/atamata/rvumf7dg
atamata
@atamata - Sí, eso es extraño, pero predecible y esperado. 31 días después del final del mes anterior para marzo es el 31 de marzo, pero para febrero es el 2 de marzo. Si desea contar a partir de fin de mes, tendrá que escribir un código personalizado para eso.
gilly3
28

Recomiendo usar una biblioteca llamada Moment.js.

Está bien probado, funciona en varios navegadores y en el lado del servidor (lo estoy usando tanto en proyectos angulares como de nodos). Tiene un gran soporte para fechas locales.

http://momentjs.com/

var threeMonthsAgo = moment().subtract(3, 'months');

console.log(threeMonthsAgo.format()); // 2015-10-13T09:37:35+02:00

.format()devuelve una representación de cadena de fecha con formato ISO 8601 . También puede usarlo con un formato de fecha personalizado como este:.format('dddd, MMMM Do YYYY, h:mm:ss a')

Jan Osch
fuente
10

Un "trazador de líneas" (en muchas líneas para una fácil lectura)) para colocar directamente en una variable:

var oneMonthAgo = new Date(
    new Date().getFullYear(),
    new Date().getMonth() - 1, 
    new Date().getDate()
);
usuario7394313
fuente
¡bonito! No estoy seguro de si es aplicable a cada escenario, pero parece funcionar lo suficientemente bien.
Devin Fields
8

Para simplificar las cosas, puede usar DateJS, una biblioteca de fechas para JavaScript:

http://www.datejs.com/

Código de ejemplo para ti:

Date.today().add({ months: -1 });
thinkdevcode
fuente
8

Esto debería manejar la suma / resta, solo ponga un valor negativo para restar y un valor positivo para sumar. Esto también resuelve el problema del crossover mensual.

function monthAdd(date, month) {
    var temp = date;
    temp = new Date(date.getFullYear(), date.getMonth(), 1);
    temp.setMonth(temp.getMonth() + (month + 1));
    temp.setDate(temp.getDate() - 1); 

    if (date.getDate() < temp.getDate()) { 
        temp.setDate(date.getDate()); 
    }

    return temp;    
}
Hodeifa Baswel
fuente
6

Si el setMonthmétodo ofrecido por gilly3 no es el que está buscando, considere:

var someDate = new Date(); // add arguments as needed
someDate.setTime(someDate.getTime() - 3*28*24*60*60);
// assumes the definition of "one month" to be "four weeks".

Se puede usar por cualquier cantidad de tiempo, solo configure los múltiplos correctos.

Niet the Dark Absol
fuente
Yo iría con la respuesta de gilly3. El suyo supone un número fijo de segundos por mes. La aritmética de la fecha indulgente de JavaScript mantendrá el día correcto. Tres meses antes del 28 de septiembre deben ser el 28 de julio.
Ray Toal
1
Me pregunto qué calcularía JavaScript el 31 de marzo menos 1 mes.
Niet the Dark Absol
1
En ese caso, obtienes el 3 de marzo (para 2011) porque eso es lo que el 31 de febrero está en modo indulgente. Pero reste 2 meses y obtendrá el 31 de enero. Según el modelo de 28 días por mes, no lo haría. Tan débil como es la Dateclase, y por mucho que se prefiera Date.js, al menos modela un calendario proleptico indulgente que es lo suficientemente bueno para uso casual.
Ray Toal
¿No deberías varios segundos a 1000 para correctamente setTime()?
Vlad Tsepelev
4

Me gusta la simplicidad de la respuesta de gilly3 , pero los usuarios probablemente se sorprenderán de que un mes antes del 31 de marzo sea el 3 de marzo. Elegí implementar una versión que se mantenga a fin de mes, así que un mes antes del 28, 29, 30 de marzo, y el 31 será el 28 de febrero cuando no sea un año bisiesto.

function addMonths(date, months) {
  var result = new Date(date),
      expectedMonth = ((date.getMonth() + months) % 12 + 12) % 12;
  result.setMonth(result.getMonth() + months);
  if (result.getMonth() !== expectedMonth) {
    result.setDate(0);
  }
  return result;
}

var dt2004_05_31 = new Date("2004-05-31 0:00"),
    dt2001_05_31 = new Date("2001-05-31 0:00"),
    dt2001_03_31 = new Date("2001-03-31 0:00"),
    dt2001_02_28 = new Date("2001-02-28 0:00"),
    result = addMonths(dt2001_05_31, -2);
console.assert(dt2001_03_31.getTime() == result.getTime(), result.toDateString());

result = addMonths(dt2001_05_31, -3);
console.assert(dt2001_02_28.getTime() == result.getTime(), result.toDateString());

result = addMonths(dt2001_05_31, 36);
console.assert(dt2004_05_31.getTime() == result.getTime(), result.toDateString());

result = addMonths(dt2004_05_31, -38);
console.assert(dt2001_03_31.getTime() == result.getTime(), result.toDateString());

console.log('Done.');

Don Kirkby
fuente
2

Ya hay una respuesta elegante, pero creo que es difícil de leer, así que hice mi propia función. Para mis propósitos, no necesitaba un resultado negativo, pero no sería difícil de modificar.

    var subtractMonths = function (date1,date2) {
        if (date1-date2 <=0) {
            return 0;
        }
        var monthCount = 0;
        while (date1 > date2){
            monthCount++;
            date1.setMonth(date1.getMonth() -1);
        }
        return monthCount;
    }
JamesD
fuente
2

var d = new Date("2013/01/01");
console.log(d.toLocaleDateString());
d.setMonth(d.getMonth() + 18);
console.log(d.toLocaleDateString());

pooja
fuente
1

Este es el código más pequeño y fácil.

   var minDate = new Date(); 
   minDate.setMonth(minDate.getMonth() - 3);

Declarar variable que tiene fecha actual. entonces solo usando la función incorporada setMonth podemos obtener una fecha de retroceso de 3 meses.

Rohit Gaidhane
fuente
-1

En mi caso, necesitaba restar 1 mes a la fecha actual. La parte importante era el número del mes, por lo que no importa en qué día del mes actual se encuentre, necesitaba el mes pasado. Este es mi código:

var dateObj = new Date('2017-03-30 00:00:00'); //Create new date object
console.log(dateObj); // Thu Mar 30 2017 00:00:00 GMT-0300 (ART)

dateObj.setDate(1); //Set first day of the month from current date
dateObj.setDate(-1); // Substract 1 day to the first day of the month

//Now, you are in the last month
console.log(dateObj); // Mon Feb 27 2017 00:00:00 GMT-0300 (ART)

Restar 1 mes a la fecha real no es precisa, es por eso que en primer lugar configuro el primer día del mes (el primer día de cualquier mes siempre es el primer día) y en segundo lugar resto 1 día, que siempre lo envía al último mes. Espero ayudarte, amigo.

var dateObj = new Date('2017-03-30 00:00:00'); //Create new date object
console.log(dateObj); // Thu Mar 30 2017 00:00:00 GMT-0300 (ART)

dateObj.setDate(1); //Set first day of the month from current date
dateObj.setDate(-1); // Substract 1 day to the first day of the month

//Now, you are in the last month
console.log(dateObj); // Mon Feb 27 2017 00:00:00 GMT-0300 (ART)

Miguel Angel
fuente
-1

   

 var date=document.getElementById("date");
    var d = new Date();
   document.write(d + "<br/>");
    d.setMonth(d.getMonth() - 6);
    document.write(d);

 if(d<date)
  document.write("lesser then 6 months");
else
  document.write("greater then 6 months");

santhosh
fuente
-1

Pase un objeto JS Date y un número entero de cuántos meses desea sumar / restar. monthsToAddpuede ser positivo o negativo Devuelve un objeto de fecha JS.

Si originalDateObjectes el 31 de marzo y pasa -1 como monthsToAdd, entonces su fecha de salida será el 28 de febrero.

Si pasa una gran cantidad de meses, digamos 36, también manejará el ajuste del año correctamente.

const addMonthsToDate = (originalDateObject, monthsToAdd) => {
  const originalDay = originalDateObject.getUTCDate();
  const originalMonth = originalDateObject.getUTCMonth();
  const originalYear = originalDateObject.getUTCFullYear();

  const monthDayCountMap = {
    "0": 31,
    "1": 28,
    "2": 31,
    "3": 30,
    "4": 31,
    "5": 30,
    "6": 31,
    "7": 31,
    "8": 30,
    "9": 31,
    "10": 30,
    "11": 31
  };

  let newMonth;
  if (newMonth > -1) {
    newMonth = (((originalMonth + monthsToAdd) % 12)).toString();
  } else {
    const delta = (monthsToAdd * -1) % 12;
    newMonth = originalMonth - delta < 0 ? (12+originalMonth) - delta : originalMonth - delta;
  }

  let newDay;

  if (originalDay > monthDayCountMap[newMonth]) {
    newDay = monthDayCountMap[newMonth].toString();
  } else {
    newDay = originalDay.toString();
  }

  newMonth = (+newMonth + 1).toString();

  if (newMonth.length === 1) {
    newMonth = '0' + newMonth;
  }

  if (newDay.length === 1) {
    newDay = '0' + newDay;
  }

  if (monthsToAdd <= 0) {
    monthsToAdd -= 11;
  }

  let newYear = (~~((originalMonth + monthsToAdd) / 12)) + originalYear;

  let newTime = originalDateObject.toISOString().slice(10, 24);

  const newDateISOString = `${newYear}-${newMonth}-${newDay}${newTime}`;

  return new Date(newDateISOString);
};
Adán
fuente
-5
Following code give me Just Previous Month From Current Month even the date is 31/30 of current date and last month is 30/29/28 days:

   <!DOCTYPE html>
<html>
<body>

<p>Click the button to display the date after changing the month.</p>

<button onclick="myFunction()">Try it</button>

<p id="demo"></p>

<script>
function myFunction() {

var d = new Date("March 29, 2017"); // Please Try the result also for "March 31, 2017" Or "March 30, 2017"
var OneMonthBefore =new Date(d);

OneMonthBefore.setMonth(d.getMonth(),0);
if(OneMonthBefore.getDate() < d.getDate()  )
{
d.setMonth(d.getMonth(),0);
}else
{
d.setMonth(d.getMonth()-1);

}

    document.getElementById("demo").innerHTML = d;
}
</script>

</body>
</html>
Mohammad Rahman
fuente
¿Cómo difiere esta respuesta de las otras 7 respuestas bastante antiguas, ya presentes?
Stephen Rauch
-5

var d = new Date();
document.write(d + "<br/>");
d.setMonth(d.getMonth() - 6);
document.write(d);

santhosh
fuente