Как рассчитать дату в 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.