Jak obliczyć datę w JavaScript trzy miesiące przed dzisiejszym dniem?


147

Próbuję ustalić datę, która jest 3 miesiące przed bieżącą datą. Aktualny miesiąc otrzymuję za pomocą poniższego kodu

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

Czy możecie podać mi logikę do obliczania i formowania daty (obiekt Datetypu danych), biorąc pod uwagę, że gdy miesiąc jest styczeń (1), 3 miesiące przed datą to październik (10)?

Odpowiedzi:


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

To działa na styczeń. Uruchom ten fragment:

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


Jest kilka zastrzeżeń ...

Miesiąc to ciekawa sprawa. Jak definiujesz 1 miesiąc? 30 dni? Większość ludzi powie, że miesiąc temu oznacza ten sam dzień miesiąca, w którym potrzebne jest cytowanie z poprzedniego miesiąca . Ale więcej niż połowa czasu, czyli 31 dni temu, a nie 30. A jeśli dzisiaj jest 31 dzień miesiąca (a nie jest to sierpień ani grudzień), to ten dzień miesiąca nie istnieje w poprzednim miesiącu.

Co ciekawe, Google zgadza się z JavaScriptem, jeśli zapytasz go, jaki dzień jest miesiąc przed kolejnym :

Wynik wyszukiwania Google dla „miesiąca przed 31 marca” pokazuje „3 marca”

Mówi się również, że jeden miesiąc ma 30,4167 dni : Wynik wyszukiwania Google dla „jednego miesiąca w dniach” pokazuje „30 .4167”

Czy zatem miesiąc przed 31 marca jest tym samym dniem, co miesiąc przed 28 marca, a 3 dni wcześniej? Wszystko zależy od tego, co masz na myśli, mówiąc „miesiąc wcześniej”. Porozmawiaj z właścicielem produktu.

Jeśli chcesz zrobić to, co robi momentjs i poprawić te błędy ostatniego dnia miesiąca, przechodząc do ostatniego dnia miesiąca, możesz zrobić coś takiego:

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

Jeśli twoje wymagania są bardziej skomplikowane, użyj trochę matematyki i napisz kod. Jesteś programistą! Nie musisz instalować biblioteki! Nie musisz kopiować i wklejać ze stosu overflow! Możesz samodzielnie opracować kod, aby robić dokładnie to, czego potrzebujesz!


var currentDate = new Date (); var currentMonth = currentDate.getMonth () -12; var pastDate = new Date (2011, currentMonth, 01); alert (pastDate); to zadziałało, sprawdzono po 12 miesiącach
KeenUser,

To jest chora odpowiedź ... Skąd mam zamiar wziąć 2012,0,15? Konwersja istniejącego miesiąca -1?
Alex G

3
@AlexG - Jeśli nie masz doświadczenia z analizowaniem dat w JavaScript, widzę, jak mój szybki przykład byłby mylący. JavaScript wyraża miesiące jako liczone od zera, gdzie styczeń jest zerowy. Aby uniknąć takiego zamieszania, zwłaszcza, że ​​nie ma to nic wspólnego z pytaniem lub moją odpowiedzią, zaktualizowałem moje demo, aby uzyskać datę z łańcucha, co powinno być bardziej intuicyjne.
gilly3

7
Wiem, że to stare, ale jeśli data to 31 marca i odejmiesz jeden miesiąc za pomocą tej metody, wynikiem jest 2 marca. jsfiddle.net/atamata/rvumf7dg
atamata

@atamata - Tak, to dziwne, ale przewidywalne i oczekiwane. 31 dni po zakończeniu poprzedniego miesiąca dla marca to 31 marca, ale dla lutego to 2 marca. Jeśli chcesz liczyć od końca miesiąca, będziesz musiał napisać niestandardowy kod.
gilly3

28

Polecam korzystanie z biblioteki o nazwie Moment.js.

Jest dobrze przetestowany, działa na różnych przeglądarkach i po stronie serwera (używam go zarówno w projektach Angular, jak i Node). Ma świetne wsparcie dla dat lokalnych.

http://momentjs.com/

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

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

.format()zwraca ciąg znaków reprezentujący datę w formacie ISO 8601 . Możesz go również używać z niestandardowym formatem daty, takim jak ten:.format('dddd, MMMM Do YYYY, h:mm:ss a')


10

„Jedna linijka” (w wielu wierszach w celu ułatwienia odczytu)) do umieszczenia bezpośrednio w zmiennej:

var oneMonthAgo = new Date(
    new Date().getFullYear(),
    new Date().getMonth() - 1, 
    new Date().getDate()
);

miły! Nie jestem pewien, czy ma to zastosowanie do każdego scenariusza, ale wydaje się, że działa wystarczająco dobrze.
Devin Fields


8

Powinno to obsługiwać dodawanie / odejmowanie, po prostu wstaw wartość ujemną, aby odjąć, i wartość dodatnią, aby dodać. To również rozwiązuje problem krzyżowania się miesiąca.

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;    
}

6

Jeśli setMonthmetoda oferowana przez gilly3 nie jest tym, czego szukasz, rozważ:

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".

Może być używany przez dowolny czas, wystarczy ustawić odpowiednią wielokrotność.


Poszedłbym z odpowiedzią Gilly3. Twój zakłada stałą liczbę sekund w miesiącu. Łagodna arytmetyka dat w JavaScript sprawi, że dzień będzie poprawny. Trzy miesiące przed 28 września powinny być 28 lipca.
Ray Toal

1
Zastanawiam się, co JavaScript obliczy 31 marca minus 1 miesiąc.
Niet the Dark Absol

1
W takim przypadku otrzymasz 3 marca (2011), ponieważ 31 lutego jest w trybie łagodnym. Ale odejmij 2 miesiące, a otrzymasz 31 stycznia. W modelu 28 dni na miesiąc nie. DateChoć klasa jest słaba i choć preferowany jest Date.js, przynajmniej modeluje łagodny kalendarz proleptyczny, który jest wystarczająco dobry do codziennego użytku.
Ray Toal

Czy nie powinieneś kilka sekund do 1000, aby poprawnie setTime()?
Vlad Tsepelev,

4

Podoba mi się prostota odpowiedzi gilly3 , ale użytkownicy prawdopodobnie będą zaskoczeni, że miesiąc przed 31 marca to 3 marca. Zdecydowałem się zaimplementować wersję, która trzyma się do końca miesiąca, a więc miesiąc przed 28, 29, 30 marca a 31 będzie 28 lutego, kiedy to nie jest rok przestępny.

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


2

Jest już elegancka odpowiedź, ale uważam, że jest trudna do odczytania, więc stworzyłem własną funkcję. Do moich celów nie potrzebowałem wyniku ujemnego, ale nie byłbym trudny do zmodyfikowania.

    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;
    }

2

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


1

To jest najmniejszy i najłatwiejszy kod.

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

Zadeklaruj zmienną, która ma aktualną datę. następnie używając wbudowanej funkcji setMonth możemy uzyskać datę wsteczną o 3 miesiące.


-1

W moim przypadku musiałem odjąć 1 miesiąc od daty bieżącej. Ważną częścią był numer miesiąca, więc nie obchodzi go, w którym dniu bieżącego miesiąca jesteś, potrzebowałem ostatniego miesiąca. To jest mój kod:

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)

Odejmowanie 1 miesiąca od aktualnej daty nie jest dokładne, dlatego na pierwszym miejscu ustawiam pierwszy dzień miesiąca (pierwszy dzień każdego miesiąca jest zawsze pierwszym dniem) a na drugim miejscu odejmuję 1 dzień, który zawsze przesyła do ostatniego miesiąca. Mam nadzieję, że ci pomogę.

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)


-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");


-1

Przekaż obiekt JS Date i liczbę całkowitą określającą, ile miesięcy chcesz dodać / odjąć. monthsToAddmoże być pozytywne lub negatywne. Zwraca obiekt daty JS.

Jeśli masz originalDateObject31 marca i przekroczysz -1 jako monthsToAdd, to datą wyjściową będzie 28 lutego.

Jeśli miniesz dużą liczbę miesięcy, powiedzmy 36, to również odpowiednio poradzi sobie z dostosowaniem roku.

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);
};

-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>

Czym ta odpowiedź różni się od 7 innych, dość starych odpowiedzi, które już istnieją?
Stephen Rauch

-5

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

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.