The aim of this application is always to indicate the 16th business day of each month (means taking into account working days and public holidays).
For this I use moment-business-days
, which is a moment.js
plugin. It calculates dates and considers working days and (preconfigured) public holidays. I use it as follows and for some dates it gives me the right result, but for some of them not. I can’t see the mistake in my code:
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>
In this example I get as a result the following dates, which sometimes is correct and sometimes not:
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 ...
Is there a quick way to solve this or is there any comparable datetime processing library, which can work with business days and calculate them flawlessly?
Advertisement
Answer
The reason the code wouldn’t work for all months is that the first day of the month is counted as a business day by default.
A condition to distinguish whether the first day actually is a business day or not should suffice (adding 16 business days when the first one is not a business day itself).
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 }