JavaScript: 获取该月剩余天数的意外结果

JavaScript: unexpected result getting number of days remaining in the month

我正在构建一个简单的脚本来显示到月底的天数,以展示对日期在 Javascript 中的工作方式的理解。这样也好,因为我明明没有。

我想获取当前日期,并将其与该月的最后一天进行比较,因为 date(this year, this month +1, day 0) - 1 day 以查看还剩多少天。我可以建立一个数组告诉它每个月有多少天,但我应该能够使用对日期的内在理解来解决这个问题。

对于预期输出,本月最后一天(8 月 31 日)- 今天(8 月 30 日)= 1。但我得到 0。

这是我目前拥有的:

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

<script>
var d = new Date();
var nxt = new Date(d.getFullYear(), d.getMonth() + 1, 0);
nxt.setDate(nxt.getDate() - 1);
document.getElementById("demo").innerHTML = nxt.getDay() - d.getDay();
</script>

目前是 AEST (GMT + 1000) 的 11 点,这是我所在的位置,以防有任何帮助。重点是制作可以随时随地使用的东西。


我的第一个怀疑是时区 - 我认为如果我使用所有 UTC 或不使用 UTC 显式,这可能会平衡。它似乎并没有这样做。我试过在不同的地方询问 UTC 值,但奇怪的是似乎只能增加不准确性,所以它 returns -1.

我相信我只是偶然发现了答案 - 当指定日期时 是从 0 到 11 计算的,但是 仍然是从 1 计数到 31。因此,指定

Date(d.getFullYear(), d.getMonth() + 1, 0);

基本上是当月最后一天的 shorthand。下一行是多余的:

nxt.setDate(nxt.getDate() - 1);

这将给出不正确的结果,因为它基本上是第二次递减。问题不在于 UTC/nonUTC,而是日期指定不正确。不确定这个 shorthand 是否会导致其他问题。

你必须记住,在浏览器中,日期总是在当前系统设置的时区内。

如果您可以使用 moments 库,它可以为您提供几乎所有您可能需要的功能,从而解决所有与日期相关的常见问题

这是 datediff 示例代码:

var today = new Date(), y = today.getFullYear(), m = today.getMonth();
var lastDay = new Date(y, m + 1, 0);
var diff = lastDay.diff(today, 'days', true);

现在,由于两个日期都是在同一个浏览器中创建的,它们将具有相同的时区,不会产生任何问题。但是,如果说从服务器返回一个日期并用 GMT/UTC 表示,那么您也需要在同一时区转换另一个日期。同样,moments.js 将能够在那里提供帮助。

对于任何想知道为什么零日值会导致这种行为的人, 提供了一个有用的解释。

以下用于计算当月剩余天数的 vanilla js 方法只是对您正在做的事情略有不同,并附有关于如何利用月份索引和第 0 天获取当前日期的最后一天的简短评论说明月.

const year = 2018;
const month = 7; // months indexed from 0 (Jan) to 11 (Dec)
const day = 30;

// current datetime
const date = new Date(year, month, day);

// add 1 to get next month, set day to 0 to roll it back to last day of current month
const last = new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate();

// difference between last day of the month and input date
const diff = last - date.getDate();
console.log(diff);

下面是一个片段,您可以在其中试验不同日期的结果。

const remainDays = (y, m, d) => {
  const result = document.querySelector('#result');
  const date = new Date(y, m, d);
  const last = new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate();
  const diff = last - date.getDate();
  result.textContent = diff;
};

const year = document.querySelector('#year');
const month = document.querySelector('#month');
const day = document.querySelector('#day');
const button = document.querySelector('button');
remainDays(year.value, month.value, day.value);
button.addEventListener('click', () => {
  remainDays(year.value, month.value, day.value);
});
div {
  padding: 5px;
  display: flex;
  flex-direction: column;
  max-width: 400px;
}
<div>
  <label for="year">Year</label>
  <input id="year" name="year" type="text" value="2018" />
</div>
<div>
  <label for="month">Month Index</label>
  <input id="month" name="month" type="text" value="7" />
  <span>Enter month index between 0 (Jan) and 11 (Dec)</span>
</div>
<div>
  <label for="day">Day</label>
  <input id="day" name="day" type="text" value="30" />
</div>
<div>
  <button>Get Month Days Remaining</button>
</div>
<div>
  <span>Result:</span>
  <span id="result"></span>
</div>