Como calcular a diferença em meses entre duas datas em c #?
Existe um equivalente do DateDiff()
método VB em C #. Preciso encontrar diferença nos meses entre duas datas que têm anos de diferença. A documentação diz que eu posso usar TimeSpan
como:
TimeSpan ts = date1 - date2;
mas isso me fornece dados em dias. Não quero dividir esse número por 30, porque nem todos os meses são 30 dias e, como os dois valores dos operandos são bem separados um do outro, receio que dividir por 30 possa me dar um valor errado.
Alguma sugestão?
DateDiff
implantação: referencesource.microsoft.com/#Microsoft.VisualBasic/… .Respostas:
Supondo que o dia do mês seja irrelevante (ou seja, a diferença entre 2011.1.1 e 31.12.2010 é 1), com data1> data2 dando um valor positivo e data2> data1 um valor negativo
Ou, supondo que você queira um número aproximado de 'meses médios' entre as duas datas, o seguinte deve funcionar para todas as diferenças de datas, exceto as muito grandes.
Observe que, se você usar a última solução, seus testes de unidade deverão indicar o período mais amplo com o qual seu aplicativo foi projetado para trabalhar e validar os resultados do cálculo de acordo.
Atualização (com agradecimentos a Gary )
Se você usar o método 'meses médios', um número um pouco mais preciso a ser usado para o 'número médio de dias por ano' é 365,2425 .
fonte
(date1.Year - date2.Year) * 12 + date1.Month - date2.Month + (date1.Day >= date2.Day ? 0 : -1)
Aqui está uma solução abrangente para retornar a
DateTimeSpan
, semelhante a aTimeSpan
, exceto que inclui todos os componentes de data, além dos componentes de hora.Uso:
Saídas:
Por conveniência, agrupei a lógica na
DateTimeSpan
estrutura, mas você pode mover o métodoCompareDates
sempre que achar melhor. Observe também que não importa que data venha antes da outra.fonte
34
dias para esta data diferença de tempo na verdade é35
timeanddate.com/date/...31
quanto à data "passa" meses com menos dias. Inverti a lógica (de modo que ela vá do início para o posterior e vice-versa) e agora acumule os meses sem modificar a data atual (e, portanto, passando entre os meses com menos dias). Ainda não tenho certeza do resultado ideal. deve ser ao comparar10/31/2012
com11/30/2012
. No momento, o resultado é1
mês.2020-02-29
para2021-06-29
- ele retorna "1a 4m 1d", mas o valor deve ser "1a 4m 0d", certo?Você poderia fazer
fonte
if ( date1.AddMonths(x).Month == date2.Month )
então você apenas usa x + 1 como meses contadosSe você deseja o número exato de meses completos, sempre positivo (2000-01-15, 2000-02-14 retorna 0), considerando que um mês inteiro é quando você alcança o mesmo dia no mês seguinte (algo como o cálculo da idade)
Editar motivo: o código antigo não estava correto em alguns casos, como:
fonte
new { From = new DateTime(2015, 12, 31), To = new DateTime(2015, 6, 30), Result = 6 }
o teste falhará, pois o resultado é 5. #new { From = new DateTime(2015, 12, 31), To = new DateTime(2016, 06, 30), Result = 6 }
. O "bug" está noto.Day < from.Day
código que não leva em consideração que os meses podem terminar em um "dia do mês" diferente. Nesse caso, de 31 de dezembro de 2015 a 30 de junho de 2016, 6 meses completos se passaram (já que junho tem 30 dias), mas seu código retornaria 5.Eu verifiquei o uso desse método no VB.NET via MSDN e parece que ele tem muitos usos. Não existe um método interno em C #. (Mesmo que não seja uma boa ideia), você pode chamar VBs em C #.
Microsoft.VisualBasic.dll
ao seu projeto como referênciaMicrosoft.VisualBasic.DateAndTime.DateDiff
no seu códigofonte
Microsoft.VisualBasic.dll
módulo precisa ser carregado, mas o tempo necessário para isso é insignificante. Não há razão para se enganar com os recursos completamente testados e úteis, apenas porque você optou por escrever seu programa em C #. (Isso vale para coisas comoMy.Application.SplashScreen
bem.)using
afirmação correta , mas duvido que haja algum dano sério.DateAndTime.Year()
existir, já queDateTime
possui umaYear
propriedade. Existe apenas para fazer o VB.NET parecer mais com o VB6. Como ex-programador VB6, eu posso apreciar este ;-)Para obter diferença em meses (inclusive no início e no final), independentemente das datas:
fonte
start
eend
é idêntico. Então você obtém o resultado 1. Como isso está correto? Por que você adiciona 1 ao resultado? Quem está votando positivamente nesta resposta: - /?Use o tempo de Noda :
(fonte de exemplo)
fonte
Eu só precisava de algo simples para atender, por exemplo, as datas de emprego em que apenas o mês / ano é inserido, de modo que desejamos anos e meses distintos trabalhados. É isso que eu uso, aqui apenas para utilidade
.NET Fiddle
fonte
Você pode usar a classe DateDiff da Time Period Library for .NET :
fonte
Aqui está minha contribuição para obter a diferença nos meses que eu achei precisos:
Uso:
Você pode criar outro método chamado DiffYears e aplicar exatamente a mesma lógica acima e AddYears em vez de AddMonths no loop while.
fonte
Isso funcionou para o que eu precisava. O dia do mês não importava no meu caso, porque sempre é o último dia do mês.
fonte
A maneira mais precisa é essa que retorna a diferença em meses por fração:
fonte
Aqui está uma solução simples que funciona pelo menos para mim. Provavelmente não é o mais rápido porque usa o recurso AddMonth do DateTime em um loop:
fonte
fonte
Isto é da minha própria biblioteca, retornará a diferença de meses entre duas datas.
fonte
Jan-31-2014
eDec-31-2013
Você pode ter uma função parecida com esta.
Por exemplo, de 27/12/2012 a 29/12/2012 passa a 3 dias. Da mesma forma, de 15/12/2012 a 15/01/2013 passa a 2 meses, porque até 14/01/2013 é 1 mês. a partir do dia 15 começa o segundo mês.
Você pode remover o "=" na segunda condição if, se não desejar incluir os dois dias no cálculo. ou seja, de 15/12/2012 a 15/01/2013 é de 1 mês.
fonte
você pode usar a seguinte extensão: Code
Implementação!
fonte
Aqui está uma solução muito mais concisa usando o VB.Net DateDiff apenas por ano, mês, dia. Você também pode carregar a biblioteca DateDiff em C #.
date1 deve ser <= date2
VB.NET
C #
fonte
Isso é uma resposta à resposta de Kirk Woll. Ainda não tenho pontos de reputação suficientes para responder a um comentário ...
Eu gostei da solução de Kirk e iria descaradamente descarná-la e usá-la no meu código, mas, quando olhei, percebi que era muito complicado. Comutação e loop desnecessários e um construtor público que não faz sentido usar.
Aqui está a minha reescrita:
Usage1, praticamente o mesmo:
Uso2, semelhante:
fonte
No meu caso, é necessário calcular o mês completo a partir da data de início até o dia anterior a esse dia no próximo mês ou do início ao fim do mês.
Ex: de 01/01/2018 a 31/01/2018 é um mês completo
Ex2: de 01/05/2018 a 02/04/2018 é um mês completo
Então, com base nisso, aqui está minha solução:
Uso:
Nota: no meu caso, era necessário calcular os dias restantes após os meses completos, portanto, se não for o seu caso, você poderá ignorar o resultado dos dias ou até mesmo alterar o método de retorno de tupla para inteiro.
fonte
Esta solução é para o cálculo de aluguel / assinatura, onde a diferença não significa subtração, deve ser o período dentro dessas duas datas.
fonte
Existem três casos: mesmo ano, ano anterior e outros anos.
Se o dia do mês não importa ...
fonte
Eu escrevi uma função para fazer isso, porque as outras maneiras não estavam funcionando para mim.
fonte
Meu entendimento da diferença total de meses entre duas datas tem uma parte integral e uma fracionária (a data importa).
A parte integrante é a diferença de meses completos.
A parte fracionária, para mim, é a diferença da% do dia (para os dias completos do mês) entre os meses inicial e final.
Com esta extensão, esses são os resultados:
fonte
Não há muitas respostas claras sobre isso, porque você está sempre assumindo as coisas.
Esta solução calcula entre duas datas nos meses entre a suposição de que você deseja salvar o dia do mês para comparação (o que significa que o dia do mês é considerado no cálculo)
Por exemplo, se você tem uma data de 30 de janeiro de 2012, 29 de fevereiro de 2012 não será um mês, mas 01 de março de 2013 será.
Foi testado minuciosamente, provavelmente o limpará mais tarde, enquanto o usamos, mas aqui:
fonte
Com base no excelente trabalho DateTimeSpan feito acima, normalizei um pouco o código; isso parece funcionar muito bem:
fonte
CompareDates(x, y)
ondex={01/02/2019 00:00:00}
ey={01/05/2020 00:00:00}
, em seguida,Months
dá-me2
Esta função estática simples calcula a fração de meses entre duas datas, por exemplo
A função assume que a primeira data é menor que a segunda data. Para lidar com intervalos de tempo negativos, pode-se modificar a função facilmente, introduzindo um sinal e uma troca de variável no início.
fonte
Conseguir calcular a diferença entre duas datas em meses é uma coisa perfeitamente lógica a se fazer e é necessária em muitos aplicativos de negócios. Os vários codificadores aqui que fizeram comentários como - qual é a diferença nos meses entre "1 de maio de 2010" e "16 de junho de 2010, qual é a diferença nos meses entre 31 de dezembro de 2010 e 1 de janeiro de 2011? - não conseguiram entender os princípios básicos dos aplicativos de negócios.
Aqui está a resposta para os 2 comentários acima - O número de meses entre 1 de maio de 2010 e 16 de junho de 2010 é de 1 mês, o número de meses entre 31 de dezembro de 2010 e 1 de janeiro de 2011 é 0. seria muito tolo calculá-los como 1,5 meses e 1 segundo, como sugeriram os codificadores acima.
As pessoas que trabalharam com cartão de crédito, processamento de hipotecas, processamento de impostos, processamento de aluguel, cálculos de juros mensais e uma vasta variedade de outras soluções comerciais concordariam.
O problema é que essa função não está incluída no C # ou no VB.NET. Datediff leva apenas em consideração anos ou o componente do mês, portanto, é realmente inútil.
Aqui estão alguns exemplos da vida real de onde você precisa e pode calcular corretamente os meses:
Você morou em um aluguel de curta duração de 18 de fevereiro a 23 de agosto. Quantos meses você ficou lá? A resposta é simples - 6 meses
Você tem uma conta bancária em que os juros são calculados e pagos no final de cada mês. Você deposita o dinheiro em 10 de junho e o retira em 29 de outubro (mesmo ano). Por quantos meses você se interessa? Resposta muito simples - 4 meses (novamente os dias extras não importam)
Nos aplicativos de negócios, na maioria das vezes, quando você precisa calcular meses, é porque precisa conhecer meses "completos" com base em como os humanos calculam o tempo; não se baseia em pensamentos abstratos / irrelevantes.
fonte
Estrutura expandida de Kirks com ToString (formato) e Duração (ms longos)
fonte
fonte