;

segunda-feira, 10 de janeiro de 2011

Como calcular datas considerando apenas dias úteis

Hoje quero compartilhar com vocês uma rotina criada para adicionar dias úteis a uma data. Ou seja, é um método que recebe dois parâmetros: uma data inicial e a quantidade de dias que devem ser adicionados a esta data,  e retorna o resultado desta soma, respeitando fins de semana e feriados. 

Desta forma, se a data inicial for 10/01/2011, e quisermos adicionar cinco dias, esta rotina irá retornar 17/01/2011 (lembre-se, valem apenas dias úteis). Para saber se determinado dia é sábado ou domingo, utilizei a propriedade DayOfWeek, da classe DateTime. Já para os feriados utilizei um lista de objetos da classe DateTime. Veja como ficou o código:

private DateTime AdicionaTempo(DateTime pDataInicial, int pDias)
{
    DateTime resultado = pDataInicial;

    while (pDias > -1)
    {
        //Se é sábado, domingo ou feriado, ando um dia pra frente
        if (resultado.DayOfWeek == DayOfWeek.Saturday || resultado.DayOfWeek == DayOfWeek.Sunday || feriados.Contains(resultado))
        {
            resultado = resultado.AddDays(1);
        }
        //Ou se quiser adicionar um dia útil (X horas trabalhadas = 1 dia útil)
        else if (pDias > 0)
        {
            resultado = resultado.AddDays(1);
            pDias -= 1;
        }
        //Se a data final for no fim de semana ou feriado
        else if (pDias == 0)
        {
            while (resultado.DayOfWeek == DayOfWeek.Saturday || resultado.DayOfWeek == DayOfWeek.Sunday || feriados.Contains(resultado))
            {
                resultado = resultado.AddDays(1);
            }
            pDias = -1;
        }
    }

    return resultado;
} 


O único inconveniente desta rotina é lista de feriados, que deve ser carregada de uma base de dados, ou criada manualmente. Então, se souber uma maneira mais eficiente de montar esta rotina, compartilhe-a conosco.

Abraços


7 comentários:

RanmaHime disse...

Boa tarde,
como eu poderia criar essa conexão com a lista de feriados? Eu já tenho o datatable, mas por mais que tente ou pesquise, não consigo fazer uma conexão que funcione e deixe os feriados invisíveis e não selecionáveis no calendário asp net. Pode me ajudar? Obrigada

Gabriel Bauermann disse...

Não entendi direito o q vc quer dizer com conexão que funcione e deixar feriados invisíveis. Me explique um pouco melhor.
Caso vc queira q o usuário não selecione uma data no seu controle do tipo calendário, joga os feriados em uma lista, e trata o evento de seleção de uma data via javascript. Verifica se o dia está na lista de feriados. Se sim, não faça nada, ou alerte o usuário.
Não sei se estamos falando da mesma coisa, mas me explique um pouco melhor seu problema. Talvez, se compreender, poderei ajudar. =)

Anônimo disse...

eu acho interessante criar um serviço em wcf que retorne um bool tipo assim vc passa uma data e ele faz um select na sua base de dados se tiver o valor cadastrado la então é feriado.

public DateTime DiasUtil (DateTime dt)
{
while (true)
{
if (dt.DayOfWeek == DayOfWeek.Saturday)
return dt.AddDays(2);
if (dt.DayOfWeek == DayOfWeek.Sunday || isferiaro == true)
return dt.AddDays(1);
return dt;
}
}

flw

Gabriel Bauermann disse...

Ou vc pode retornar todos os feriados no período solicitado. Assim vc faz apenas 1 acesso a banco.

Unknown disse...
Este comentário foi removido pelo autor.
Unknown disse...

esta aqui uma maneira faciel de exibir todos os dias uteis incluindo os feriados Nacionais de Moçambique
public static DateTime AdicionaTempo(DateTime pDataInicial, int pDias)
{
// DateTime dias = DateTime.Now;
DateTime resultado = pDataInicial;
DateTime diaFeriado = resultado.AddDays(pDias);

while (pDias > -1)
{
//Se é sábado, domingo ou feriado, ando um dia pra frente
if (resultado.DayOfWeek == DayOfWeek.Saturday || resultado.DayOfWeek == DayOfWeek.Sunday || FeriadosNacionaisDeMocambique(resultado))
{
resultado = resultado.AddDays(1);
}
//Ou se quiser adicionar um dia útil (X horas trabalhadas = 1 dia útil)
else if (pDias > 0)
{
resultado = resultado.AddDays(1); pDias -= 1;
}
//Se a data final for no fim de semana ou feriado
else if (pDias == 0)
{
while (resultado.DayOfWeek == DayOfWeek.Saturday || resultado.DayOfWeek == DayOfWeek.Sunday || FeriadosNacionaisDeMocambique(resultado))
{
resultado = resultado.AddDays(1);
}
pDias = -1;
}
}
return resultado;
}

// Feriados Nacionais
public static Boolean FeriadosNacionaisDeMocambique(DateTime verificarData)
{
DateTime dataSerVerificada = new DateTime(verificarData.Year, verificarData.Month, verificarData.Day);
int verificarDataAno = verificarData.Year;
int a = (int)verificarDataAno % 4;
int b = (int)verificarDataAno % 7;
int c = (int)verificarDataAno % 19;
int d = (int)((19 * c) + 24) % 30;
int e = (int)((2 * a) + (4 * b) + (6 * d) + 5) % 7;
int diaPascoa = 22 + d + e;
int mesPascoa = 3;
if (diaPascoa > 31)
{
diaPascoa = d + e - 9;
mesPascoa = 4;
}
List feriados = new List();
feriados.Add(new DateTime(verificarDataAno, mesPascoa, diaPascoa).ToString()); //Pascoa
feriados.Add(new DateTime(verificarDataAno, 1, 1).ToString()); //Dia de Ano Novo (Confraternização Universal)
feriados.Add(new DateTime(verificarDataAno, 2, 3).ToString()); //Dia dos Herois Mocambicanos
feriados.Add(new DateTime(verificarDataAno, 4, 7).ToString()); //Dia da Mulher Mocambicana
feriados.Add(new DateTime(verificarDataAno, 5, 1).ToString()); //Dia Internacional dos Trabalhadores
feriados.Add(new DateTime(verificarDataAno, 6, 25).ToString()); //Dia da Independencia Nacional
feriados.Add(new DateTime(verificarDataAno, 9, 7).ToString()); //Dia da Vitoria
feriados.Add(new DateTime(verificarDataAno, 9, 25).ToString()); //|Dia das Forcas Armadas de Libertacao de Mocambique
feriados.Add(new DateTime(verificarDataAno, 10, 4).ToString());//Dia da Paz e Reconciliacao
feriados.Add(new DateTime(verificarDataAno, 12, 25).ToString()); //Natal

return feriados.Contains(dataSerVerificada.ToString());
}

Gabriel Bauermann disse...

Excelente, Domingos!
Obrigado pela colaboração.

Postar um comentário