34

Date 对象的getMonth()方法似乎有一个错误。假设 Dated2013-01-31,我尝试d像这样设置月份:

const d = new Date(); // 2013-01-31

d.setMonth(8);
console.log(d.getMonth());

结果是9。为什么?我在 Chrome 和 Firefox 中都对此进行了测试。

我发现当它是一个月的 31 号、30 号或 29 号时,将日期设置为天数较少的月份会导致getMonth返回错误的值。

4

7 回答 7

48

让我们分解一下:

var d = new Date(); // date is now 2013-01-31
d.setMonth(1);      // date is now 2013-02-31, which is 3 days past 2013-02-28
x = d.getMonth();   // what to do, what to do, 3 days past 2013-02-28 is in March
                    // so, expect x to be March, which is 2

仅当 的日期值d大于传递给 的月份中的最大天数时,才会出现此问题setMonth()。否则,它会按您的预期工作。

于 2013-02-04T04:37:04.730 回答
20

最简单的解决方案是向 setMonth 添加第二个参数:

var d = new Date();
d.setMonth(8,1);
d.getMonth(); //outputs 8

http://www.w3schools.com/jsref/jsref_setmonth.asp

Date.setMonth(月,日)

日:可选。表示月份日期的整数预期值为 1-31,但允许使用其他值:

0 将导致上个月的最后一天 -1 将导致上个月最后一天的前一天 如果该月有 31 天:

32 将导致下个月的第一天如果该月有 30 天:

32 将导致下个月的第二天

于 2014-07-31T11:42:21.863 回答
11

JavaScript 中的月份是从 0 到 11 表示的。第 1 个月将是只有 28/29 天的 2 月,因此当您将月份设置为 1 时,它会尝试将日期自动更正为 3 月以使日期有意义(自 2 月 31 日起,没有意义)。使用 toDateString 函数试试看我的意思:

 var d = new Date('2013/01/31');
 d.setMonth(2);
 console.log(d.toDateString()); // outputs Match 3rd, 2013

也许有点奇怪,但不是越野车。

于 2013-02-04T04:36:04.253 回答
8

在 javascript 中,月份从 0 开始。假设今天是 02/04/2012,当您 setMonth(1) 时,它将尝试设置为 2 月。由于 2 月的最大天数是 28/29,它移动到下个月(3 月,即 2)

于 2013-02-04T04:38:33.557 回答
1

这里的 setMonth 不是你所期望的,在更好的库中会发生什么。如果将日期 31.x.yyyy 设置为 x+1,则下个月 (x+1) 可能没有 31 天。所以 31.x+1.yyyy 会变成 1.x+2.yyyy。

在这种情况下,月份将增加 2 - 日期完全改变。

我在更改二月->三月时遇到了这个问题,感谢上帝,这只是一个测试。

于 2016-06-29T11:20:00.057 回答
1

这与当前的本地日期有关,即使您设置的日期是过去或将来的日期(假设您正确使用月份范围 0-11)。这是因为当您初始化 Date() 时,它使用的是当前日期。当您使用 setFullYear()、setMonth() 或 setDate() 修改日期时,默认的“当前”值仍然存在并且可以改变日期。

如果您当月的当天(今天)是该月的 31 日,然后您使用 setMonth()、setDate() 设置过去的日期,其中该月的天数少于您当前的 31 天,则 Date() 将给出你错误的月份,即使你特别说明它。这是因为当你 setMonth() 时,当前日期值 31,在你设置的月份中不存在,将它推到下个月。然后,当您设置日期时,月份永远不会变回。

如果您在月份之前设置月份中的某天 - setDate()、setMonth(),这可以解决问题,但还有另一个类似的问题/错误。如果您当前的月份只有 30 天,而您尝试设置的日期有 31 天,则它将月份的日期设置为 1,而不是 31。如果您设置前一个月,则可以解决此问题 - setMonth() , setDate(),但是你又回到了第一个问题。

解决方案:

  1. 获取值,然后同时设置月份和月份的日期(如 reetah 建议的那样) - setMonth(8,1)
  2. 使用可选值设置年份以初始化 setFullYear(1972, 0, 1),然后是 setMonth, setDate。
  3. 设置月份,设置日期,然后验证月份是否等于您设置的月份,如果不是,请再次设置 - setMonth()、setDate()、setMonth()

function formatDate(date) {
  var monthNames = [
    "January", "February", "March",
    "April", "May", "June", "July",
    "August", "September", "October",
    "November", "December"
  ];

  var day = date.getDate();
  var monthIndex = date.getMonth();
  var year = date.getFullYear();

  return day + ' ' + monthNames[monthIndex] + ' ' + year;
}

var date = new Date();
if (date.getDate() < 31) {
	$("#mydate").text("YOUR LOCAL DATE (on your computer) MUST BE SET TO THE 31st for this bug to show.");
} else {
  date.setFullYear(1972);
  date.setMonth(8); // (month-1)
  date.setDate(24);
  var breakdown = "<br>Day: " + date.getDate() + "<br>Month: " + date.getMonth() + "<br>Year: " + date.getFullYear();
  $("#mydate").html("Set as September (8)<br><br>" + formatDate(date) + breakdown);

  var date = new Date();
  date.setFullYear(1972);
  date.setMonth(8, 24); // (month-1)
  var breakdown = "<br>Day: " + date.getDate() + "<br>Month: " + date.getMonth() + "<br>Year: " + date.getFullYear();
  $("#mydate4").html("Set as September (8) but set day before month<br><br>" + formatDate(date) + breakdown);

  date.setFullYear(1972);
  date.setMonth(9); //October (month-1)
  date.setDate(24);
  var breakdown = "<br>Day: " + date.getDate() + "<br>Month: " + date.getMonth() + "<br>Year: " + date.getFullYear();
  $("#mydate2").html("Set as October (9)<br><br>" + formatDate(date) + breakdown);

  var date = new Date();
  date.setFullYear(1972);
  date.setMonth(7); //Aug (month-1)
  date.setDate(24);
  var breakdown = "<br>Day: " + date.getDate() + "<br>Month: " + date.getMonth() + "<br>Year: " + date.getFullYear();
  $("#mydate3").html("Set as August (7)<br><br>" + formatDate(date) + breakdown);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
September 1972 has only 30 days.  If your current local day is 31, the Date will return October 1972 when you specify September before you specify the day of the month.
<br><br><div id="mydate" style="color: red;">
</div>
<br><br>
<div id="mydate4">
</div><br><br>
<div id="mydate2">
</div>
<br><br>
<div id="mydate3">
</div>

于 2017-05-31T13:24:00.467 回答
-3

我只是这样解决了:

例子

var d = new Date('2013/01/31');

m = d.getMonth();

month = m*100/100 + 1;

Var month包含正确的值。

于 2013-08-29T10:39:41.603 回答