计算日期时考虑 public 节假日和周末 moment.js 和时刻工作日

Calculate dates considering public holidays and weekends with moment.js and moment-business-days

此应用程序的目的是始终指示每个月的第 16 个工作日(意味着考虑工作日和 public 假期)。

为此,我使用 moment-business-days,这是一个 moment.js 插件。它计算日期并考虑工作日和(预配置的)public 假期。我按如下方式使用它,对于某些日期,它会给我正确的结果,但对于其中一些则不会。我看不到我的代码中的错误:

myHolidays = [
  { holidayDate: "2020-06-01", description: "holiday 1" },
  { holidayDate: "2020-06-02", description: "holiday 2" },
  { holidayDate: "2020-06-03", description: "holiday 3" },  
  { holidayDate: "2020-06-06", description: "weekend saturday" },
  { holidayDate: "2020-06-07", description: "weekend sunday" },
  { holidayDate: "2020-06-11", description: "holiday 6" },
  { holidayDate: "2020-06-13", description: "weekend saturday" },
  { holidayDate: "2020-06-14", description: "weekend sunday" },
  { holidayDate: "2020-06-20", description: "weekend saturday" },
  { holidayDate: "2020-06-21", description: "weekend sunday" },
  { holidayDate: "2020-06-27", description: "weekend saturday" },
  { holidayDate: "2020-06-28", description: "weekend sunday" },
];

moment.updateLocale('de', {
   holidays: myHolidays.map(i => i.holidayDate),
   holidayFormat: 'YYYY-MM-DD'
});

var startDate = moment("2020-01-01").startOf('month')
var endDate = moment("2020-12-01")
var eachMonthWith16 = [];

function generate16InEachMonth() {
  let monthsList = []
  // loop by months
  while (endDate > startDate) {
    monthsList.push(new Date(moment(this.startDate).businessAdd(15, 'days')))
    startDate = startDate.add(1, "month").startOf('month')
  }
  return monthsList
}

console.log(generate16InEachMonth())
.as-console-wrapper { top: 0; max-height: 100% !important; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.27.0/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment-business-days/1.2.0/index.js"></script>

在这个例子中,我得到以下日期,有时是正确的,有时是错误的:

Month  Actual  Target  Correct
Jan    22      22      yes
Feb    24      21      no
March  23      20      no
April  22      22      yes
May    22      22      yes
June   25      26      no
July   22      22      yes
...

有没有快速解决这个问题的方法,或者有没有类似的日期时间处理库,可以处理工作日并完美地计算它们?

该代码不适用于所有月份的原因是默认情况下该月的第一天被计为工作日。

区分第一天是否真的是工作日的条件就足够了(当第一天本身不是工作日时加上 16 个工作日)。

function generate16InEachMonth() {
  let monthsList = []
  // loop by months
  while (endDate > startDate) {
    var daysToAdd = (startDate.isBusinessDay()) ? 15 : 16
    monthsList.push(new Date(moment(this.startDate).businessAdd(daysToAdd, 'days')))
    startDate = startDate.add(1, "month").startOf('month')
  }
  return monthsList
}