Как рассчитать дату в JavaScript за три месяца до сегодняшнего дня?


147

Я пытаюсь сформировать дату, которая за 3 месяца до текущей даты. Я получаю текущий месяц по приведенному ниже коду

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

Ребята, можете ли вы дать мне логику для вычисления и формирования даты (объект типа Dateданных), учитывая, что когда месяцем является январь (1), за 3 месяца до даты будет OCtober (10)?

Ответы:


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

Это работает на январь. Запустите этот фрагмент:

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


Есть некоторые предостережения ...

Месяц это любопытная вещь. Как вы определяете 1 месяц? 30 дней? Большинство людей скажут , что один месяц назад средства в тот же день месяца , в предыдущем месяце цитации . Но более половины времени, то есть 31 день назад, а не 30. И если сегодня 31 число месяца (а это не август или декабрь), то этот день месяца не существует в предыдущем месяце.

Интересно, что Google соглашается с JavaScript, если вы спросите его, какой день за месяц до следующего :

Результаты поиска Google за «месяц до 31 марта» показывают «3 марта»

В нем также говорится, что один месяц длится 30,4167 дней : Результаты поиска Google "один месяц в днях" показывают "30 .4167"

Итак, один месяц до 31 марта совпадает с днем ​​до 28 марта, 3 днями ранее? Все зависит от того, что вы подразумеваете под «месяцем ранее». Поговорите с владельцем вашего продукта.

Если вы хотите сделать то же, что и momentjs, и исправить эти ошибки в последний день месяца, перейдя к последнему дню месяца, вы можете сделать что-то вроде этого:

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

Если ваши требования сложнее, используйте математику и напишите немного кода. Вы разработчик! Вам не нужно устанавливать библиотеку! Вам не нужно копировать и вставлять из stackoverflow! Вы можете разработать код самостоятельно, чтобы делать именно то, что вам нужно!


var currentDate = new Date (); var currentMonth = currentDate.getMonth () -12; var pastDate = new Date (2011, currentMonth, 01); оповещения (pastDate); это сработало, проверено за 12 месяцев
KeenUser

Это больной ответ ... Откуда я собираюсь получить 2012,0,15? Преобразовать существующий месяц -1?
Алекс Г

3
@AlexG - Если вы новичок в разборе дат в JavaScript, то я вижу, что мой быстрый пример может сбить с толку. JavaScript выражает месяцы в виде нуля, где январь равен нулю. Чтобы избежать такой путаницы, тем более что это не имеет никакого отношения к вопросу или моему ответу, я обновил демо, чтобы получить дату из строки, которая должна быть более интуитивной.
gilly3

7
Я знаю, что это старое время, но если дата 31 марта, и вы вычитаете один месяц, используя этот метод, результатом является 2 марта. jsfiddle.net/atamata/rvumf7dg
атамата

@atamata - Да, это странно, но предсказуемо и ожидаемо. 31 день после окончания предыдущего месяца для марта - 31 марта, а для февраля - 2 марта. Если вы хотите считать с конца месяца, вам придется написать для этого какой-то специальный код.
gilly3

28

Я рекомендую использовать библиотеку под названием Moment.js.

Он хорошо протестирован, работает на разных браузерах и на стороне сервера (я использую его как в проектах Angular, так и в Node). Имеет большую поддержку дат локали.

http://momentjs.com/

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

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

.format()возвращает строковое представление даты , отформатированный в ISO 8601 формате. Вы также можете использовать его с пользовательским форматом даты, например так:.format('dddd, MMMM Do YYYY, h:mm:ss a')


10

«Один вкладыш» (на много строк для удобного чтения), который нужно поместить непосредственно в переменную:

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

отлично! Не уверен, что это применимо к каждому сценарию, но, кажется, работает достаточно хорошо.
Девин Филдс

8

Чтобы упростить задачу, вы можете использовать DateJS, библиотеку дат для JavaScript:

http://www.datejs.com/

Пример кода для вас:

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

8

Это должно обрабатывать сложение / вычитание, просто положить отрицательное значение для вычитания и положительное значение для добавления. Это также решает проблему пересечения месяцев.

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

Если setMonthметод, предложенный gilly3, не тот, который вам нужен, подумайте:

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

Может быть использован в течение любого количества времени, просто установите правильные кратные.


Я бы пошел с ответом gilly3. Ваш предполагает фиксированное количество секунд в месяц. Мягкая арифметика дат в JavaScript сохранит правильность дня. Три месяца до 28 сентября должны быть 28 июля.
Рэй Тоал

1
Интересно, каким будет JavaScript 31 марта минус 1 месяц?
Niet the Dark Absol

1
В этом случае вы получите 3 марта (на 2011 год), потому что это то, что 31 февраля находится в снисходительном режиме. Но вычтите 2 месяца, и вы получите 31 января. Под модель 28 дней в месяц вы бы не стали. DateНесмотря на то, что класс слаб , и хотя Date.js предпочтителен, он, по крайней мере, моделирует мягкий пролептический календарь, который достаточно хорош для случайного использования.
Рэй Тоал

Разве вы не должны несколько секунд до 1000, чтобы правильно setTime()?
Влад Цепелев

4

Мне нравится простота ответа gilly3 , но пользователи, вероятно, будут удивлены тем, что месяц до 31 марта - 3 марта. Я решил внедрить версию, которая будет работать до конца месяца, поэтому за месяц до 28, 29, 30 марта, и 31 все будет 28 февраля, когда это не високосный год.

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

Уже есть элегантный ответ, но я считаю, что его трудно читать, поэтому я сделал свою собственную функцию. Для моих целей я не нуждался в отрицательном результате, но это не было бы трудно изменить.

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


1

Это самый маленький и простой код.

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

Объявите переменную с текущей датой. затем, просто используя встроенную функцию setMonth, мы можем получить 3 месяца назад.


-1

В моем случае мне нужно было вычесть 1 месяц до текущей даты. Важной частью был номер месяца, поэтому не важно, в каком дне текущего месяца вы находитесь, мне нужно было в прошлом месяце. Это мой код:

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 месяц из фактической даты не точно, поэтому в первую очередь я устанавливаю первый день месяца (первый день любого месяца всегда является первым днем), а во вторую очередь я вычитаю 1 день, который всегда отправляет вас в последний месяц. Надеюсь помочь тебе чувак.

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

Передайте объект JS Date и целое число от того, сколько месяцев вы хотите добавить / вычесть. monthsToAddможет быть положительным или отрицательным. Возвращает объект даты JS.

Если ваш originalDateObject31 марта, и вы передаете -1 как monthsToAdd, то ваша дата выхода будет 28 февраля.

Если вы проведете большое количество месяцев, скажем, 36, он также будет корректно корректировать год.

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>

Чем этот ответ отличается от 7 других, довольно старых, уже существующих?
Стивен Раух

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.