Calculando a diferença de dias úteis entre duas datas utilizando JavaScript
Neste artigo vamos ver como calcular a diferença de dias úteis entre duas datas utilizando JavaScript.
Primeiro vamos ver quais as datas iniciais e finais que vamos trabalhar.
data1 = '2021-01-01';
data2 = '2021-12-31';
Vamos pegar esta string de data e criar uma data utilizando a função Date()
var arr1 = data1.split('-');
var arr2 = data2.split('-');
var dataAtual = new Date(arr1[0],arr1[1]-1, arr1[2]);
var dataFinal = new Date(arr2[0],arr2[1]-1, arr2[2]);
var ano_inicial = dataAtual.getFullYear();
var ano_final = dataFinal.getFullYear();
var ano = ano_inicial;
Foram criados dois arrays auxiliares com o conteudo das datas informadas. Para separar uma string e converter o seu conteudo em array utilizamos o método split da string da data. O separador foi o "-". Para criar a data, com base no array auxiliar, informamos o ano, mês e dia. Usando a função Date para criar a data inicial e final evitamos problemas com fuso horário, já que a data vai respeitar o fuso horário do navegador do usuário e evitar um problema comum no cálculo de datas, onde em algum casos o resultado fica menor em 1 dia.
Uma observação muito importante. Ao trabalhar com a função Date, o primeiro mês, que é janeiro, deve ser informado como zero. Ou seja, eu preciso subtrair 1 ao mês da data informada.
Nosso próximo passo é criar um array auxiliar que contenha todos os feriados contidos dentro do intervalo de datas informado. Alguns feriados tem data fixa, e outros tem data variável. Começando pelos feriados de data fixa. Vamos criar uma função auxiliar que vai nos permitir calcular os feriados de acordo com o ano inicial e ano final informados.
function FeriadosFixos(ano){
var resultados = [];
//Array de datas no formato mes/dia.
//OBS: O primeiro mes é 0 e o último mes é 11
var datas = [[0, 1], [3, 21],[4, 1], [8, 7], [9, 12], [10, 2], [10, 15], [11, 25]];
for (z = 0; z < datas.length; z++){
resultados.push(new Date(ano, datas[z][0], datas[z][1]).getTime());
}
return resultados;
}
data1 = '2021-01-01';
data2 = '2021-12-31';
var arr1 = data1.split('-');
var arr2 = data2.split('-');
var dataAtual = new Date(arr1[0],arr1[1]-1, arr1[2]);
var dataFinal = new Date(arr2[0],arr2[1]-1, arr2[2]);
var ano_inicial = dataAtual.getFullYear();
var ano_final = dataFinal.getFullYear();
var ano = ano_inicial;
for (x = ano; x <= ano_final; x++){
console.log(FeriadosFixos(x));
}
Neste exemplo o resultado da função gerou um array auxiliar chamado feriados para os feriados do ano informado. Para adicionar cada data fixa no array, utilizamos novamente a função Date. Seus parâmetros na ordem são ano, mês e dia. Dentro da função auxiliar, criamos um array contendo os meses e dias dos feriados com data fixa.
Agora vamos ver os feriados variáveis. Os feriados com data variável dependem da data da páscoa. Primeiro, vamos criar uma função auxiliar para calcular a data da Páscoa de acordo com um ano informado
function Pascoa(Y) {
var C = Math.floor(Y/100);
var N = Y - 19*Math.floor(Y/19);
var K = Math.floor((C - 17)/25);
var I = C - Math.floor(C/4) - Math.floor((C - K)/3) + 19*N + 15;
I = I - 30*Math.floor((I/30));
I = I - Math.floor(I/28)*(1 - Math.floor(I/28)*Math.floor(29/(I + 1))*Math.floor((21 - N)/11));
var J = Y + Math.floor(Y/4) + I + 2 - C + Math.floor(C/4);
J = J - 7*Math.floor(J/7);
var L = I - J;
var M = 3 + Math.floor((L + 40)/44);
var D = L + 28 - 31*Math.floor(M/4);
return new Date(Y, M, D);
}
Vamos precisar também de duas funções auxiliares, para aumentar ou subtrair dias a uma data informada
function DataAdicionar(data_informada, quantidade) {
var fator = 24 * 60 * 60 * 1000;
var nova_data = new Date(data_informada.getTime() + quantidade * fator);
nova_data.setHours(0,0,0,0);
return nova_data;
}
function DataSubtrair(data_informada, quantidade) {
var fator = 24 * 60 * 60 * 1000;
var nova_data = new Date(data_informada.getTime() - quantidade * fator);
nova_data.setHours(0,0,0,0);
return nova_data;
}
E agora utilizando estas funções auxiliares, vamos calcular os feriados com data variável.
var feriados = [];
for (x = ano; x <= ano_final; x++){
//OBS: O primeiro mes é 0 e o último mes é 11
//Feriados fixos.
feriados = feriados.concat(FeriadosFixos(ano));
console.log('Pascoa');
console.log(Pascoa(ano));
data_pascoa = Pascoa(ano);
//Feriados variaveis de acordo com a data da Pascoa
feriados.push(data_pascoa.getTime());
feriados.push(DataAdicionar(data_pascoa, 60).getTime());
feriados.push(DataSubtrair(data_pascoa, 48).getTime());
feriados.push(DataSubtrair(data_pascoa, 47).getTime());
feriados.push(DataSubtrair(data_pascoa, 2).getTime());
ano++;
}
console.log(feriados);
Os feriados variáveis são a páscoa, a sexta-feira santa, os dias de carnaval e o Corpus Christi
Uma observação. Como a função FeriadosFixos retorna um array com os feriados do ano, para juntar este array com o array de feriados do período selecionado utilizamos o método concat do array de feriados.
Agora que temos os feriados, podemos verificar a quantidade de dias uteis entre duas datas.
while (dataAtual <= dataFinal) {
if (dataAtual.getDay() !== 0 && dataAtual.getDay() !== 6) {
if (!feriados.includes(dataAtual.getTime())){
numDiasUteis++;
}
}
dataAtual = DataAdicionar(dataAtual,1);
}
console.log(numDiasUteis);
Para o calculo de dias fizemos um loop usando WHILE entre a data inicial e a data final, e fizemos o incremento da data em 1 dia usando a função auxiliar que criamos.
Para validar se a data atual é um feriado, utilizamos o includes do array feriados para verificar se aquela data existe no array de feriados.
if (!feriados.includes(dataAtual.getTime())){
numDiasUteis++;
}
Em nosso exemplo não consideremos o sábado e o domingo como dia útil. Para verificar o dia da semana da data informa, utilizamos o método getDay da data informada.
if (dataAtual.getDay() !== 0 && dataAtual.getDay() !== 6) {
//Codigo a ser executado
}
O retorno é um número inteiro. Ele vai retornar 6 para sábado e 0 para domingo.
Para encerrar, vamos criar uma função para encapsular toda esta lógica. Nosso código completo ficaria da seguinte forma:
function DataAdicionar(data_informada, quantidade) {
var fator = 24 * 60 * 60 * 1000;
var nova_data = new Date(data_informada.getTime() + quantidade * fator);
nova_data.setHours(0,0,0,0);
return nova_data;
}
function DataSubtrair(data_informada, quantidade) {
var fator = 24 * 60 * 60 * 1000;
var nova_data = new Date(data_informada.getTime() - quantidade * fator);
nova_data.setHours(0,0,0,0);
return nova_data;
}
function FeriadosFixos(ano){
var resultados = [];
//Array de datas no formato mes/dia.
//OBS: O primeiro mes é 0 e o último mes é 11
var datas = [[0, 1], [3, 21],[4, 1], [8, 7], [9, 12], [10, 2], [10, 15], [11, 25]];
for (z = 0; z < datas.length; z++){
resultados.push(new Date(ano, datas[z][0], datas[z][1]).getTime());
}
return resultados;
}
function Pascoa(Y) {
var C = Math.floor(Y/100);
var N = Y - 19*Math.floor(Y/19);
var K = Math.floor((C - 17)/25);
var I = C - Math.floor(C/4) - Math.floor((C - K)/3) + 19*N + 15;
I = I - 30*Math.floor((I/30));
I = I - Math.floor(I/28)*(1 - Math.floor(I/28)*Math.floor(29/(I + 1))*Math.floor((21 - N)/11));
var J = Y + Math.floor(Y/4) + I + 2 - C + Math.floor(C/4);
J = J - 7*Math.floor(J/7);
var L = I - J;
var M = 3 + Math.floor((L + 40)/44);
var D = L + 28 - 31*Math.floor(M/4);
return new Date(Y, M, D);
}
function getnumDiasUteis(startDate, dataFinal) {
var numDiasUteis = 0;
var arr1 = startDate.split('-');
var arr2 = dataFinal.split('-');
var dataAtual = new Date(arr1[0],arr1[1]-1, arr1[2]);
dataFinal = new Date(arr2[0],arr2[1]-1, arr2[2]);
var ano_inicial = dataAtual.getFullYear();
var ano_final = dataFinal.getFullYear();
var ano = ano_inicial;
var feriados = [];
for (x = ano; x <= ano_final; x++){
//OBS: O primeiro mes é 0 e o último mes é 11
//Feriados fixos.
feriados = feriados.concat(FeriadosFixos(ano));
data_pascoa = Pascoa(ano);
//Feriados variaveis de acordo com a data da Pascoa
feriados.push(data_pascoa.getTime());
feriados.push(DataAdicionar(data_pascoa, 60).getTime());
feriados.push(DataSubtrair(data_pascoa, 48).getTime());
feriados.push(DataSubtrair(data_pascoa, 47).getTime());
feriados.push(DataSubtrair(data_pascoa, 2).getTime());
ano++;
}
while (dataAtual <= dataFinal) {
if (dataAtual.getDay() !== 0 && dataAtual.getDay() !== 6) {
if (!feriados.includes(dataAtual.getTime())){
numDiasUteis++;
}
}
dataAtual = DataAdicionar(dataAtual,1);
}
return numDiasUteis;
}
console.log('dias uteis');
console.log(getnumDiasUteis('2021-01-01', '2021-12-31'));