Eu preciso encontrar 2 elegantes implementações completas de
public static DateTime AddBusinessDays(this DateTime date, int days)
{
// code here
}
and
public static int GetBusinessDays(this DateTime start, DateTime end)
{
// code here
}
O (1) preferível (sem loops).
EDITAR: Por dias úteis quero dizer dias úteis (segunda, terça, quarta, quinta, sexta). Sem feriados, apenas fins de semana excluídos.
Já tenho algumas soluções feias que parecem funcionar, mas me pergunto se existem maneiras elegantes de fazer isso. obrigado
Isso é o que escrevi até agora. Funciona em todos os casos e também faz negativos. Ainda precisa de uma implementação GetBusinessDays
public static DateTime AddBusinessDays(this DateTime startDate,
int businessDays)
{
int direction = Math.Sign(businessDays);
if(direction == 1)
{
if(startDate.DayOfWeek == DayOfWeek.Saturday)
{
startDate = startDate.AddDays(2);
businessDays = businessDays - 1;
}
else if(startDate.DayOfWeek == DayOfWeek.Sunday)
{
startDate = startDate.AddDays(1);
businessDays = businessDays - 1;
}
}
else
{
if(startDate.DayOfWeek == DayOfWeek.Saturday)
{
startDate = startDate.AddDays(-1);
businessDays = businessDays + 1;
}
else if(startDate.DayOfWeek == DayOfWeek.Sunday)
{
startDate = startDate.AddDays(-2);
businessDays = businessDays + 1;
}
}
int initialDayOfWeek = (int)startDate.DayOfWeek;
int weeksBase = Math.Abs(businessDays / 5);
int addDays = Math.Abs(businessDays % 5);
if((direction == 1 && addDays + initialDayOfWeek > 5) ||
(direction == -1 && addDays >= initialDayOfWeek))
{
addDays += 2;
}
int totalDays = (weeksBase * 7) + addDays;
return startDate.AddDays(totalDays * direction);
}
AddBusinessDays
implementação na pergunta acima (que na verdade foi uma resposta excluída que propus desfazer a exclusão; um mod copiou essa resposta para a pergunta): Na minha opinião, esta solução é melhor do que todas as respostas até agora porque é a única aquele que lida corretamente com valores negativos, sábado e domingo como fonte e não precisa de uma biblioteca de terceiros. (Eu fiz um pequeno programa para testar as diferentes soluções aqui.) Eu adicionaria apenasif (businessDays == 0) return startDate;
no início do método para obter o resultado correto para este caso extremo também.AddBusinessDays
foi a solução mais geral aqui que funcionou em todos os casos que eu preciso. Copiei para um dos meus projetos atuais (após uma ligeira modificação e tradução para C ++), obrigado pelo código :) Ajudou muito, pois é surpreendentemente difícil acertar todos os casos extremos.Respostas:
Última tentativa para sua primeira função:
A segunda função, GetBusinessDays, pode ser implementada da seguinte forma:
fonte
usando Fluent DateTime :
o código interno é o seguinte
fonte
Criei uma extensão que permite adicionar ou subtrair dias úteis. Use um número negativo de businessDays para subtrair. Acho que é uma solução bastante elegante. Parece funcionar em todos os casos.
Exemplo:
fonte
Para mim, eu precisava ter uma solução que pulasse os fins de semana e fosse negativa ou positiva. Meu critério era que se fosse para a frente e pousasse em um fim de semana, teria que avançar para segunda-feira. Se fosse voltar e pousar em um fim de semana, teria que pular para sexta-feira.
Bem, você entendeu;)
Acabei escrevendo esta aula de extensão
Ele usa esse método que achei útil em outro lugar ...
Se você não quiser se preocupar com isso, você pode simplesmente substituir
if (MyClass.IsBusinessDay(date))
seif ((date.DayOfWeek != DayOfWeek.Saturday) && (date.DayOfWeek != DayOfWeek.Sunday))
Então agora você pode fazer
ou
Aqui estão os resultados de alguns testes:
fonte
fonte
Estou atrasado para a resposta, mas fiz uma pequena biblioteca com todas as customizações necessárias para fazer operações simples em dias úteis ... Deixo aqui: Working Days Management
fonte
A única solução real é fazer com que essas chamadas acessem uma tabela de banco de dados que define o calendário do seu negócio. Você poderia codificá-lo para uma semana de trabalho de segunda a sexta-feira sem muita dificuldade, mas lidar com os feriados seria um desafio.
Editado para adicionar solução parcial não elegante e não testada:
Além disso, violei o requisito de sem loops.
fonte
Estou ressuscitando este post porque hoje tive que encontrar uma maneira de excluir não só os dias de semana de sábado e domingo, mas também feriados. Mais especificamente, eu precisava lidar com vários conjuntos de feriados possíveis, incluindo:
Eventualmente, eu vim com o seguinte conjunto de classes auxiliares / extensões: embora eles não sejam ostensivamente elegantes, já que fazem um uso massivo de loops ineficientes, eles são decentes o suficiente para resolver meus problemas para sempre. Estou descartando todo o código-fonte aqui neste post, esperando que seja útil para outra pessoa também.
Código fonte
Informação de uso
O código é bastante autoexplicativo, no entanto, aqui estão alguns exemplos para explicar como você pode usá-lo.
Adicione 10 dias úteis (ignorando apenas os dias da semana de sábado e domingo)
Adicione 10 dias úteis (ignorando sábado, domingo e todos os feriados invariáveis do país para 2019)
Adicione 10 dias úteis (pulando sábado, domingo e todos os feriados italianos em 2019)
Adicione 10 dias úteis (pulando sábado, domingo, todos os feriados italianos e feriados específicos de Roma para 2019)
As funções acima e os exemplos de código são explicados com mais detalhes nesta postagem do meu blog.
fonte
fonte
Eu queria um "AddBusinessDays" que suportasse números negativos de dias para adicionar e acabei com o seguinte:
Não é necessário fazer um loop, então deve ser razoavelmente rápido, mesmo para adições "grandes".
Funciona com dias expressos como um número de dias corridos desde a época, desde que isso seja exposto pela nova classe JDK8 LocalDate e eu estava trabalhando em Java. Deve ser simples de se adaptar a outras configurações.
As propriedades fundamentais são que
addDays
sempre retorna um dia da semana, e que para todosd
en
,daysBetween(d, addDays(d, n)) == n
Observe que, teoricamente falando, adicionar 0 dias e subtrair 0 dias deve ser uma operação diferente (se sua data for um domingo, adicionar 0 dias deve levar você para segunda-feira e subtrair 0 dias deve levar você para sexta-feira). Como não existe 0 negativo (fora do ponto flutuante!), Optei por interpretar um argumento n = 0 como significando adicionar zero dias.
fonte
Eu acredito que esta poderia ser uma maneira mais simples de GetBusinessDays:
fonte
Aqui está o meu código com a data de partida e a data de entrega no cliente.
Boa codificação.
fonte
fonte
fonte
Espero que isso ajude alguém.
fonte