Em C # /. NET TimeSpan
tem TotalDays
, TotalMinutes
, etc, mas eu não posso descobrir uma fórmula para meses totais diferença. Dias variáveis por mês e anos bissextos continuam me excitando. Como posso obter TotalMonths ?
Editar Desculpe por não ser mais claro: eu sei que realmente não consigo entender isso, TimeSpan
mas pensei em usar TotalDays
e TotalMinutes
seria um bom exemplo para expressar o que estava procurando ... exceto que estou tentando obter o total de meses.
Exemplo: 25 de dezembro de 2009 a 6 de outubro de 2009 = 2 meses totais. 6 de outubro a 5 de novembro é igual a 0 meses. Em 6 de novembro, 1 mês. Em 6 de dezembro, 2 meses
Respostas:
Você não poderá obter isso de a
TimeSpan
, porque um "mês" é uma unidade de medida variável. Você terá que calcular por conta própria e precisará descobrir exatamente como deseja que funcione.Por exemplo, as datas devem gostar
July 5, 2009
eAugust 4, 2009
gerar uma diferença de um mês ou zero meses? Se você diz que deve produzir um, entãoJuly 31, 2009
e quantoAugust 1, 2009
? É que um mês? É simplesmente a diferença dosMonth
valores para as datas ou está mais relacionada a um período de tempo real? A lógica para determinar todas essas regras não é trivial; portanto, você deve determinar por conta própria e implementar o algoritmo apropriado.Se tudo o que você deseja é simplesmente uma diferença nos meses - desconsiderando completamente os valores da data -, você pode usar o seguinte:
Observe que isso retorna uma diferença relativa, o que significa que se
rValue
for maior quelValue
, então o valor de retorno será negativo. Se você quer uma diferença absoluta, pode usar o seguinte:fonte
(Eu sei que essa é uma pergunta antiga, mas ...)
Isso é relativamente doloroso em .NET puro. Eu recomendaria minha própria biblioteca Noda Time , que é especialmente projetada para coisas como esta:
(Existem outras opções, por exemplo, se você quiser apenas uma contagem de meses, mesmo ao longo dos anos, você usaria
Period period = Period.Between(start, end, PeriodUnits.Months);
)fonte
Period.Between
. Editou o código para que ele funcione com o NodaTime 1.3.1.Talvez você não queira saber sobre frações mensais; E esse código?
fonte
Você terá que definir o que você quer dizer com TotalMonths para começar.
Uma definição simples coloca um mês em 30,4 dias (365,25 / 12).
Além disso, qualquer definição incluindo frações parece inútil, e o valor inteiro mais comum (meses inteiros entre datas) também depende de regras comerciais não padrão.
fonte
Eu escrevi um método de extensão muito simples
DateTime
eDateTimeOffset
para fazer isso. Eu queria que ele funcionasse exatamente como umaTotalMonths
propriedadeTimeSpan
funcionaria: por exemplo, retorne a contagem de meses completos entre duas datas, ignorando os meses parciais. Por se basear,DateTime.AddMonths()
ele respeita diferentes comprimentos de meses e retorna o que um humano entenderia como um período de meses.(Infelizmente, você não pode implementá-lo como um método de extensão no TimeSpan, porque isso não retém o conhecimento das datas reais usadas, e por meses elas são importantes.)
O código e os testes estão disponíveis no GitHub . O código é muito simples:
E passa em todos esses casos de teste de unidade:
fonte
Você precisa resolver isso às vezes. Como você lida com os dias stub no final dependerá do que você deseja usá-lo.
Um método seria contar o mês e depois corrigir os dias no final. Algo como:
fonte
Eu faria assim:
fonte
return (dtOther.Month - dtThis.Month) + 12 * (dtOther.Year - dtThis.Year);
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á.
Ele foi testado minuciosamente, provavelmente o limpará mais tarde enquanto o usamos, e leva duas datas em vez de um Timespan, o que provavelmente é melhor. Espero que isso ajude mais alguém.
fonte
A resposta aceita funciona perfeitamente quando você quer meses inteiros.
Eu precisava de meses parciais. Esta é a solução que encontrei por meses parciais:
Eu também precisava de uma diferença de ano com a mesma necessidade de anos parciais. Aqui está a solução que eu vim com:
fonte
YearDifference
função quandolValue.Month < rValue.Month
- eu fixo que agora, você pode querer rever ...Velha pergunta eu sei, mas pode ajudar alguém. Eu usei a resposta aceita @Adam acima, mas depois verifiquei se a diferença é 1 ou -1 e verifique se é a diferença completa de um mês. Portanto, 21/07/55 e 20/08/55 não seriam um mês inteiro, mas 21/07/55 e 21/07/55 seriam.
fonte
fonte
O problema com meses é que não é realmente uma medida simples - eles não são de tamanho constante. Você precisaria definir suas regras para o que deseja incluir e trabalhar a partir daí. Por exemplo, de 1 de janeiro a 1 de fevereiro - você pode argumentar que há 2 meses envolvidos ou pode-se dizer que é um mês. Então, que tal "de 1 de janeiro às 20:00" a "1 de fevereiro às 00:00" - não é um mês inteiro. Isso é 0? 1? e o contrário (1 de janeiro de 00:00 a 1 de fevereiro de 20:00) ... 1? 2?
Primeiro defina as regras, então você terá que codificá-lo, receio ...
fonte
Se você deseja obter um resultado
1
entre28th Feb
e1st March
:fonte
Esta biblioteca calcula a diferença de meses, considerando todas as partes do DateTime:
fonte
Abaixo, na verdade, é a maneira mais precisa de fazê-lo, uma vez que a definição de "1 mês" muda dependendo do mês em que é, e nenhuma das outras respostas leva isso em consideração! Se você deseja obter mais informações sobre o problema que não está incorporado na estrutura, pode ler esta postagem: Um objeto de período de tempo real com anos e meses (no entanto, não é necessário ler essa publicação para entender e usar a função abaixo, funciona 100%, sem as imprecisões inerentes à aproximação que outras pessoas adoram usar - e sinta-se à vontade para substituir a função .ReverseIt pela função .Reverse incorporada que você pode ter em sua estrutura (está aqui para ser completo).
Observe que você pode obter qualquer número de precisão de datas / horas, segundos e minutos ou segundos, minutos e dias, em qualquer lugar até anos (que conteria 6 partes / segmentos). Se você especificar os dois primeiros e tiver mais de um ano, ele retornará "1 ano e 3 meses atrás" e não retornará o restante porque você solicitou dois segmentos. se tiver apenas algumas horas, retornará apenas "2 horas e 1 minuto atrás". Obviamente, as mesmas regras se aplicam se você especificar 1, 2, 3, 4, 5 ou 6 segmets (no máximo 6, pois segundos, minutos, horas, dias, meses, anos e anos produzem apenas 6 tipos). Ele também corrige problemas gramaticais como "minutos" vs "minuto", dependendo de se levar 1 minuto ou mais, o mesmo para todos os tipos, e a "sequência" gerada sempre estará gramaticalmente correta.
Aqui estão alguns exemplos para uso: bAllowSegments identifica quantos segmentos serão exibidos ... ou seja: se 3, a string de retorno seria (como exemplo) ...
"3 years, 2 months and 13 days"
(não incluirá horas, minutos e segundos como os três primeiros) categorias são retornadas); se, no entanto, a data era uma data mais recente, como algo há alguns dias atrás, especificar os mesmos segmentos (3) retornará"4 days, 1 hour and 13 minutes ago"
, então isso leva tudo em consideração!se bAllowSegments for 2, ele retornará
"3 years and 2 months"
e se 6 (valor máximo) retornará"3 years, 2 months, 13 days, 13 hours, 29 minutes and 9 seconds"
, mas lembre-se de que seráNEVER RETURN
algo assim"0 years, 0 months, 0 days, 3 hours, 2 minutes and 13 seconds ago"
, pois entende que não há dados de data nos 3 principais segmentos e os ignora, mesmo se você especificar 6 segmentos , então não se preocupe :). Obviamente, se houver um segmento com 0, isso será levado em consideração ao formar a string e será exibido como"3 days and 4 seconds ago"
e ignorando a parte "0 horas"! Aproveite e comente se quiser.Obviamente, você precisará de uma função "ReplaceLast", que aceita uma string de origem e um argumento que especifique o que precisa ser substituído, e outro argumento que especifique com o que você deseja substituí-lo, e substitui apenas a última ocorrência dessa string ... incluí o meu, se você não tiver um ou não quiser implementá-lo, então aqui está, ele funcionará "como está" sem nenhuma modificação necessária. Eu sei que a função reverseit não é mais necessária (existe em .net), mas a função ReplaceLast e ReverseIt são transferidas dos dias anteriores à net, portanto, desculpe o quão datada ela pode parecer (ainda funciona 100%, usando por mais de dez anos, pode garantir que eles estão livres de erros) ... :). Felicidades.
fonte
Se você deseja o número exato, não pode, apenas no Timespan, já que precisa saber em quais meses está negociando e se está lidando com um ano bissexto, como você disse.
Escolha um número aproximado ou remexa-se com o DateTimes original
fonte
http://www.astro.uu.nl/~strous/AA/en/reken/juliaansedag.html
Se você pode obter a hora convertida de um número de dia da data gregoriana em dia juliano , basta criar um operador para fazer comparações do número de dia zuliano, que pode ser do tipo duplo para obter meses, dias, segundos etc. link para um algoritmo de conversão de gregoriano para juliano.
fonte
Não existe uma maneira integrada de fazer isso com precisão no idiomático-c #. Existem algumas soluções alternativas, como este exemplo do CodeProject que as pessoas codificaram.
fonte
Se você está lidando com meses e anos, precisa de algo que saiba quantos dias cada mês tem e quais anos são anos bissextos.
Digite o calendário gregoriano (e outras implementações de calendário específicas da cultura ).
Embora o Calendário não forneça métodos para calcular diretamente a diferença entre dois pontos no tempo, ele possui métodos como
fonte
fonte
O método retorna uma lista que contém 3 elementos: primeiro é o ano, o segundo é o mês e o elemento final é o dia:
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
Muito tarde para o jogo, mas imagino que isso possa ser útil para alguém. A maioria das pessoas tende a medir mês a mês por data, excluindo o fato de que os meses ocorrem em diferentes variações. Usando esse quadro de pensamento, criei uma linha que compara as datas para nós. Usando o seguinte processo.
Se o ano final não for maior, executamos o mesmo que 2A / 2B, mas sem adicionar os 12 meses, porque não precisamos avaliar o ano todo.
fonte
Minha opinião sobre esta resposta também usa um método de extensão , mas pode retornar um resultado positivo ou negativo.
Alguns testes:
fonte
Combinando duas das respostas acima, outro método de extensão é:
Obrigado a @AdamRobinson e @MarkWhittaker
fonte
Calcular o número de meses entre 2 datas:
fonte