У меня есть этот код для расчета дней между датами и пропуска праздников.
var gon = {};
gon["holiday"] = "2015-08-28,2015-09-25,2016-08-31,2016-08-07,2015-08-13,2016-08-29,2016-01-07,2015-10-31".split(",");
// 2 helper functions - moment.js is 35K minified so overkill in my opinion
function pad(num) { return ("0" + num).slice(-2); }
function formatDate(date) { var d = new Date(date), dArr = [d.getFullYear(), pad(d.getMonth() + 1), pad(d.getDate())];return dArr.join('-');}
function calculateDays(first,last) {
var aDay = 24 * 60 * 60 * 1000,
daysDiff = parseInt((last.getTime()-first.getTime())/aDay,10);
if (daysDiff>0) {
for (var i = first.getTime(), lst = last.getTime(); i <= lst; i += aDay) {
var d = new Date(i);
console.info(d.getDay());
if (d.getDay() == 6 || d.getDay() == 0 // weekend
|| gon.holiday.indexOf(formatDate(d)) != -1) {
daysDiff--;
}
}
}
return daysDiff;
}
Как я могу использовать звездочку * вместо года, чтобы охватить все годы. Я не хочу так поступать
gon["holiday"] = "2018-08-28,2018-09-25,2019-08-28,2019-09-25,2020-08-28,2020-09-25,2021-08-28,2021-09-25".split(",");
Могу я сделать что-то подобное
gon["holiday"] = "*-08-28,*-09-25".split(",");
Но разве это не уничтожило бы цель? Иногда праздники выпадают на другой день в зависимости от года. Как бы вы определить, какой день был подходящим, без указания года?
Эти даты всегда одни и те же, за исключением Рождества.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Этот код может сделать всю работу за вас:
gon["holiday"]= [...Array(10)].map((_,i) => (2015+i) + "-08-28");
Полученные результаты:
(10) ["2015-08-28", "2016-08-28", "2017-08-28", "2018-08-28", "2019-08-28", "2020-08-28", "2021-08-28", "2022-08-28", "2023-08-28", "2024-08-28"]
Это хороший способ создать 10 годовых дат, но я не уверен, что он решит проблему, поскольку ни одна из дат на самом деле не повторяется.
Вы можете использовать findIndex и предоставить ему функцию, которая будет соответствовать только дню и месяцу вместо года, например:
var gon = {};
gon["holiday"] = "*-08-28,*-09-25".split(",");
function pad(num) { return ("0" + num).slice(-2); }
function formatDate(date) { var d = new Date(date), dArr = [d.getFullYear(), pad(d.getMonth() + 1), pad(d.getDate())];return dArr.join('-');}
function calculateDays(first,last) {
var aDay = 24 * 60 * 60 * 1000,
daysDiff = parseInt((last.getTime()-first.getTime())/aDay,10);
if (daysDiff>0) {
for (var i = first.getTime(), lst = last.getTime(); i <= lst; i += aDay) {
var d = new Date(i);
console.info(d.getDay());
if (d.getDay() == 6 || d.getDay() == 0 // weekend
|| gon.holiday.findIndex((h)=>formatDate(d).replace(/[^-]+-/, '') == h.replace(/[^-]+-/, '')) != -1) {
daysDiff--;
}
}
}
return daysDiff;
}
Я использую регулярное выражение для удаления года, оно удаляет первое вхождение тире и любые символы перед ним.
У вас может быть массив праздников с фиксированными годовщинами в формате MM-DD:
var fixedHols = ['08-28','09-25'];
другой для тех, кто движется более или менее беспорядочно, например, пасха, рамадан, дивали:
var movingHols = ['YYYY-MM-DD',...]
а другой - для праздников, основанных на правилах, который создается для данного года, например, первый понедельник мая или вторник, следующий за первым понедельником ноября, или что-то еще, а затем проверяет даты по ним, например
function isHoliday(date) {
let z = n => (n<10?'0':'')+n;
let fixedHols = ['08-28','09-25'];
let ymd = formatDate(date);
let md = ymd.slice(-5);
let movingHols = [ /* dates as YYY-MM-DD */ ];
let rulesHols = [ /* generate YYY-MM-DD for date.getFullYear() */ ];
// If date is in any array return true, otherwise return false
return [fixedHols, movingHols, rulesHols].some((hols, i) => hols.includes(i? ymd : md));
}
function formatDate(d) {
var z = n => (n<10?'0':'')+n;
return d.getFullYear()+'-'+z(d.getMonth()+1)+'-'+z(d.getDate());
}
[new Date(2018,7,27), // 27 Aug
new Date(2018,7,28), // 28 Aug
new Date(2018,7,29), // 29 Aug
new Date(2021,7,28), // 28 Aug
new Date(2018,8,25), // 25 Sep
new Date(2018,8,26)] // 26 Sep
.forEach(d =>
console.info(`Is ${formatDate(d)} a holiday? ${isHoliday(d)?'Yes':'No'}`)
);
Что вы можете. В вашем цикле вам также нужно сохранить текущий год. Затем замените звездочку на текущий год.