使用 JavaScript 获取给定月份的给定工作日

Get a given weekday in a given month with JavaScript

本文关键字:工作日 JavaScript 使用 获取      更新时间:2023-09-26

我试图获取某个日期落下的月份的第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;                                                                                                                     

}

您必须在

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

以下代码片段演示了更正的函数。

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 天。一般来说,给定nn == 1意味着给定工作日的第一次出现,我们必须提前 (n - 1) * 7 天。

上所述,如果date是该月的第一天,我们可以通过前进来获得weekday的第n次出现

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

您的代码似乎工作正常。要添加月份,您可以使用 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;

我刚刚对 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;
}