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

时间:2015-08-24 22:52:31

标签: javascript algorithm date

我正试图获得第n个工作日 - 例如,某个某个日期所在的第二个星期日 -

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

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

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

由于某种原因,以下代码无效。

我错过了什么?

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;                                                                                                                     

}

2 个答案:

答案 0 :(得分:8)

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

以下代码段演示了更正后的功能。

&#13;
&#13;
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)));
&#13;
body {
  font-family: sans-serif;
}
&#13;
&#13;
&#13;

有一种更好的方法可以在不循环的情况下计算所需的日期。我们首先考虑当月第一天的工作日。假设它是星期六,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是该月的第一天,我们可以通过推进nweekday出现

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

每月第一天过后。

此方法在下面实施。

&#13;
&#13;
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)));
&#13;
body {
  font-family: sans-serif;
}
&#13;
&#13;
&#13;

答案 1 :(得分:0)

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