【问题标题】:Get a given weekday in a given month with JavaScript使用 JavaScript 获取给定月份的给定工作日
【发布时间】:2015-08-24 22:52:31
【问题描述】:

我正在尝试获取某个日期所在月份的第 n 个工作日(例如,第二个星期日)。

例如,如果日期是 2015 年 8 月 24 日,我想这样做:

nthDayOfMonth(0, 2, new Date(2015, 7, 24))

并获得 2015 年 8 月 9 日(8 月的第二个星期日)。然后我希望能够在日期上添加一个月,再次调用该函数,并获得 2015 年 9 月 13 日(9 月的第二个星期日)。

由于某种原因,以下代码无法正常工作。

我错过了什么?

function nthDayOfMonth(day, n, date) {                                                                                              
    console.log(day);
    console.log(n);
    var count = 0; 
    var idate = new Date(date);                                                                                                       

    idate.setDate(1);                                                                                                                 

    while ((count) < n) {                                                                                                             
      idate.setDate(idate.getDate() + 1);
      if (idate.getDay() == day) {
        count++;                                                                                                                      
      }                                                                                                                               
    }                                                                                                                                 

return idate;                                                                                                                     

}

【问题讨论】:

  • 您是否考虑到月份是从 0 开始的(例如 8 月 == 7)
  • 另外,我想今天实际上是 8/24/15,而不是 9/24/15。
  • 哇....它计算正确,我只是没有正确阅读计算器。
  • 我刚刚修改了我的答案,加入了一种直接计算所需日期的方法。没有循环!

标签: javascript algorithm date


【解决方案1】:

在增加月份的日期之前,您必须检查 idate.getDay()。否则,如果所需的工作日是每月的第一天,您将得到错误的答案。

下面的sn-p演示了修正后的功能。

function print(s) {
  document.write(s + '<br />');
}

function nthWeekdayOfMonth(weekday, n, date) {
  var count = 0,
      idate = new Date(date.getFullYear(), date.getMonth(), 1);
  while (true) {
    if (idate.getDay() === weekday) {
      if (++count == n) {
        break;
      }
    }
    idate.setDate(idate.getDate() + 1);
  }
  return idate;
}

             // Second Sunday of the current month.
var date = new Date();
print(date = nthWeekdayOfMonth(0, 2, date)); 
             // Second Sunday of next month.
date.setMonth(date.getMonth() + 1);
print(date = nthWeekdayOfMonth(0, 2, date));

             // First Tuesday of September 2015.
print(nthWeekdayOfMonth(2, 1, new Date(2015, 8)));
             // First Wednesday of September 2015.
print(nthWeekdayOfMonth(3, 1, new Date(2015, 8)));
             // Second Tuesday of September 2015.
print(nthWeekdayOfMonth(2, 2, new Date(2015, 8)));
             // Second Wednesday of September 2015.
print(nthWeekdayOfMonth(3, 2, new Date(2015, 8)));
body {
  font-family: sans-serif;
}

有一种更好的方法可以在不循环的情况下计算所需的日期。我们首先考虑每月第一天的工作日。假设今天是星期六,JavaScript 调用 6,而您正在寻找星期日,即 0

要到达该月的第一个星期日,您必须将日期提前这个天数:

0 - 6 + 7

结果是1。计算是如何进行的? 0 - 6 是从工作日6 到工作日0 的天数,为了将负值转换为有效的工作日,我们添加7

一般来说,从工作日a到工作日b的天数是

(b - a + 7) % 7

继续这个例子,假设我们想要一个月的第一个星期日。在那种情况下,我们已经到了。但是如果我们想要一个月的第二天,我们必须将日期提前 7 天。一般来说,给定n,使得n == 1 表示给定工作日的第一次出现,我们必须提前(n - 1) * 7 天。

总而言之,如果date 是该月的第一天,我们可以通过前进到达nth 出现的weekday

(weekday - date.getDay() + 7) % 7 + (n - 1) * 7

当月第一天之后的天数。

这种方法在下面实现。

function print(s) {
  document.write(s + '<br />');
}

function nthWeekdayOfMonth(weekday, n, date) {
  var date = new Date(date.getFullYear(), date.getMonth(), 1),
      add = (weekday - date.getDay() + 7) % 7 + (n - 1) * 7;
  date.setDate(1 + add);
  return date;
}

             // Second Sunday of the current month.
var date = new Date();
print(date = nthWeekdayOfMonth(0, 2, date)); 
             // Second Sunday of next month.
date.setMonth(date.getMonth() + 1);
print(date = nthWeekdayOfMonth(0, 2, date));

             // First Tuesday of September 2015.
print(nthWeekdayOfMonth(2, 1, new Date(2015, 8)));
             // First Wednesday of September 2015.
print(nthWeekdayOfMonth(3, 1, new Date(2015, 8)));
             // Second Tuesday of September 2015.
print(nthWeekdayOfMonth(2, 2, new Date(2015, 8)));
             // Second Wednesday of September 2015.
print(nthWeekdayOfMonth(3, 2, new Date(2015, 8)));
body {
  font-family: sans-serif;
}

【讨论】:

  • 这不就是切换if语句顺序和日期增量的功能吗?
  • 如果您要切换 if 语句和递增操作的顺序,您将在到达循环开头的测试之前递增日期。如果count &lt; n,您不能在测试之前增加日期。您必须尽快退出循环count == n
【解决方案2】:

您的代码似乎运行良好。要添加一个月,您可以使用d.setMonth(d.getMonth()+1)

试试这个演示:

function nthDayOfMonth(day, n, date) {
	var count = 0,
	    idate = new Date(date);
	idate.setDate(1);

	while (count < n) {
		idate.setDate(idate.getDate() + 1);
		if (idate.getDay() == day) { count++; }
	}

	return idate;
}

// Today : 2015-08-24
var today = new Date();

// Second Sunday of current month : 2015-08-09
var res = nthDayOfMonth(0, 2, today);

// res plus 1 month : 2015-09-09 (Wednesday)
var plusOne = new Date( res );
plusOne.setMonth(plusOne.getMonth() + 1);

// Second Sunday of next month : 2015-09-13
var res2 = nthDayOfMonth(0, 2, plusOne);

document.body.innerHTML = 'Today is <br>' + today + '<br>'
                        + 'Second Sunday of current month is <br>'  + res + '<br>'
                        + 'If you add a month to it, you get <br>'  + plusOne + '<br>'
                        + 'And second Sunday of that month is <br>' + res2;

【讨论】:

    【解决方案3】:

    我刚刚对 Michael Laszlo 的出色答案进行了调整,以允许调用者提供 n==5(或任何更大的值)以表明需要该月的最后一个工作日:

    function nthWeekdayOfMonth(weekday, n, date) {
      var month = date.getMonth();
      var date = new Date(date.getFullYear(), month, 1),
          add = (weekday - date.getDay() + 7) % 7 + (n - 1) * 7;
    
      // make sure that we stay in the same month
      do {
        date.setMonth(month);
        date.setDate(1 + add);
        add -= 7;
      } while (date.getMonth() != month);
    
      return date;
    }
    

    【讨论】:

      猜你喜欢
      • 2012-01-13
      • 1970-01-01
      • 1970-01-01
      • 2021-08-12
      • 2017-06-08
      • 2014-07-09
      • 1970-01-01
      • 2022-07-29
      • 1970-01-01
      相关资源
      最近更新 更多