Using a while adding up days will solve the problem:
while (month === date.getMonth()) {
if (date.getDay() === type) count++;
date.setDate(date.getDate() + 1); // testar o próximo dia
}
But the increment of date.getDate() + 1
will generate increments and on average 30 loops, most of which are unnecessary if the required rule is a specific day of the week just add up +7
inside the loop instead of +1
and check if it’s the same month after and then yes make the sum count++
, the function a little optimized can look like this (as the test done at the end of the answer became almost 3 times faster):
function getDaysByType(type, month, year) {
const date = new Date(year ? year : new Date().getFullYear(), month, 1, 0, 0, 0);
var count = 0, increment = 1;
while (month === date.getMonth()) {
if (date.getDay() === type) {
count++;
increment = 7;
}
date.setDate(date.getDate() + increment); // testar o próximo dia
}
return count;
}
console.log('Quantidade de Sábados em Janeiro:', getDaysByType(0, 0));
console.log('Quantidade de Sábados em Fevereiro:', getDaysByType(0, 1));
console.log('Quantidade de Sábados em Março:', getDaysByType(0, 2));
console.log('Quantidade de Sábados em Abril:', getDaysByType(0, 3));
console.log('Quantidade de Sábados em Maio:', getDaysByType(0, 4));
console.log('Quantidade de Sábados em Junho:', getDaysByType(0, 5));
console.log('Quantidade de Sábados em Julho:', getDaysByType(0, 6));
This way it will be 4 to 11 loops instead of 28 to 31 loops, which made ~70% faster.
However I have another proposal, to use the BASIC MATHEMATICS, because if we know that a day of the week can appear between 4 and 5 times in a same month with that we have already obtained by a calculation, we will only need to know which the first day of the week of a month and which the last
Thus became ~90% faster:
Recalling that 0 = Saturday, 1 = Sunday, 2 = Monday, 3 = Tuesday, 4 = Wednesday, 5 = Thursday, 6 = Friday
Month 0 (January) to 11 (December)
function sumWeekDaysInMonth(weekday, month, year)
{
if (!year) year = new Date().getFullYear();
// Obtem o ultimo dia do mês
var daysInMonth = new Date(year, month + 1, 0).getDate();
// Obtem primeiro dia da semana do mês
var firstWeekDay = new Date(year, month, 1).getDay();
return Math.floor((daysInMonth + (weekday + firstWeekDay) % 7) / 7);
}
console.log('Quantidade de Sábados em Janeiro (ano atual):', sumWeekDaysInMonth(6, 0));
console.log('Quantidade de Sábados em Fevereiro (ano atual):', sumWeekDaysInMonth(6, 1));
console.log('Quantidade de Sábados em Março (ano atual):', sumWeekDaysInMonth(6, 2));
console.log('----');
console.log('Quantidade de Sábados em Janeiro 1988:', sumWeekDaysInMonth(6, 0, 1988));
console.log('Quantidade de Sábados em Fevereiro 1988:', sumWeekDaysInMonth(6, 1, 1988));
console.log('Quantidade de Sábados em Março 1988:', sumWeekDaysInMonth(6, 2, 1988));
To better understand, we use the % to get what is left in a division, then:
day of the week + first day of the week of the month / total days week (7)
In January it was (6 + 3) %7 = 2 (would be as 6+3=9 and 9/7=1.2, rounding is 2)
Then sum the number of days in the month and divide by 7, 4 was the remaining result of division:
(31 + 2) / 7 = 4,714285714285714
Then use Math.floor()
to return the smallest integer that will be "4" for the month of January 2020
View the benchmark of all codes: https://jsbench.me/lwkdh223r9/1
Depends on the month.
– Danizavtz
Exactly! I need a script that tells me the number of days according to the current month.
– Guilherme Nunes
Hello, William, suggestion, most mathematical cases will be much more efficient than loop/recursion, so in the case here I did with mathematical operation that got 90% faster than with loops: https://answall.com/a/466531/3635, for sporadic uses is indifferent, but if you are going to consult many months it may be very advantageous to test this proposal.
– Guilherme Nascimento