Estou usando a java.util.Date
classe Java no Scala e quero comparar um Date
objeto e a hora atual. Eu sei que posso calcular o delta usando getTime ():
(new java.util.Date()).getTime() - oldDate.getTime()
No entanto, isso me deixa com um long
milissegundo de representação. Existe alguma maneira mais simples e agradável de obter um delta de tempo?
Date
,Calendar
eSimpleDateFormat
”.java.time.Period
e / ouDuration
. Veja a resposta de Basil Bourque abaixo .Respostas:
Date
Infelizmente, a API do JDK está terrivelmente quebrada. Eu recomendo usar a biblioteca Joda Time .Joda Time tem um conceito de tempo Intervalo :
EDIT: By the way, Joda tem dois conceitos:
Interval
para representar um intervalo de tempo entre dois instantes de tempo (representam o tempo entre 8:00 e 10:00), e umDuration
que representa um período de tempo sem os limites de tempo reais (por exemplo, representa duas horas!)Se você se preocupa apenas com comparações de tempo, a maioria das
Date
implementações (incluindo a do JDK) implementa aComparable
interface que permite usar oComparable.compareTo()
fonte
Comparable.compareTo()
, nãoComparable.compare()
.java.time
pacote no Java 8 é inspirado no Joda-Time, mas não é um substituto imediato. Cada um tem os seus prós e contras. Felizmente, você não precisa escolher entre eles. Use cada um por seus pontos fortes, desde que tenha cuidado com suasimport
declarações. Veja esta outra resposta, por exemplo, de java.time.Diferença simples (sem lib)
E então você pode ligar para:
para obter a diferença das 2 datas em minutos.
TimeUnit
éjava.util.concurrent.TimeUnit
um enum Java padrão que vai de nanos a dias.Dif. Legível por humanos (sem lib)
http://ideone.com/5dXeu6
A saída é algo como
Map:{DAYS=1, HOURS=3, MINUTES=46, SECONDS=40, MILLISECONDS=0, MICROSECONDS=0, NANOSECONDS=0}
, com as unidades encomendadas.Você apenas precisa converter esse mapa em uma sequência amigável.
Atenção
Os trechos de código acima calculam uma diferença simples entre 2 instantes. Isso pode causar problemas durante uma mudança de horário de verão, como explicado neste post . Isso significa que, se você calcular a diferença entre datas sem tempo, poderá ter um dia / hora ausente.
Na minha opinião, a diferença de datas é subjetiva, principalmente em dias. Você pode:
conte o número de 24 horas decorridas: dia + 1 - dia = 1 dia = 24h
conte o número de tempo decorrido, cuidando do horário de verão: dia + 1 - dia = 1 = 24h (mas usando o horário da meia-noite e o horário de verão, pode ser 0 e 23h)
conte o número de
day switches
, o que significa dia + 13h - dia 11h = 1 dia, mesmo que o tempo decorrido seja de apenas 2h (ou 1h se houver horário de verão: p)Minha resposta é válida se sua definição de data e dia coincidir com o 1º caso
Com o JodaTime
Se você estiver usando o JodaTime, poderá obter o diff por 2 instantes (datas suportadas por milhões de ReadableInstant) com:
Mas você também pode obter o diff para datas / horários locais:
fonte
Observe que isso funciona com datas UTC; portanto, a diferença pode ser um dia de folga se você observar as datas locais. E fazê-lo funcionar corretamente com datas locais requer uma abordagem completamente diferente devido ao horário de verão.
fonte
(endDate.getTime() - startDate.getTime())
com que seja convertido emint
vez do resultado final, e você está recebendo um estouro inteiro.Usando a estrutura java.time integrada ao Java 8+:
Resultado:
Para mais informações, consulte o Tutorial Oracle e o padrão ISO 8601 .
fonte
Period
vez deDuration
para datas.Você precisa definir seu problema mais claramente. Você pode simplesmente pegar o número de milissegundos entre os dois
Date
objetos e dividir pelo número de milissegundos em 24 horas, por exemplo ... mas:Date
está sempre no UTCfonte
tl; dr
Converta seus
java.util.Date
objetos obsoletos em sua substituiçãojava.time.Instant
,. Em seguida, calcule o tempo decorrido como aDuration
.Formato ISO 8601:
PnYnMnDTnHnMnS
A norma sensata ISO 8601 define uma representação textual concisa de um período de tempo como um número de anos, meses, dias, horas etc. O padrão exige esse período como uma duração . O formato é
PnYnMnDTnHnMnS
onde osP
meios "Período", oT
separam a parte da data da parte da hora e entre os números são seguidos por uma letra.Exemplos:
P3Y6M4DT12H30M5S
três anos, seis meses, quatro dias, doze horas, trinta minutos e cinco segundos
PT4H30M
Quatro horas e meia
java.time
O java.time quadro construído em Java 8 e posterior suplanta as velhas problemáticas
java.util.Date
/java.util.Calendar
classes. As novas classes são inspiradas no altamente bem - sucedido framework Joda-Time , pretendido como seu sucessor, similar em conceito, mas re-arquitetado. Definido pelo JSR 310 . Prorrogado pelo projeto ThreeTen-Extra . Veja o tutorial .Momento
A
Instant
classe representa um momento na linha do tempo no UTC com uma resolução de nanossegundos (até nove (9) dígitos de uma fração decimal).Melhor evitar as classes herdadas, como
Date
/Calendar
. Mas se você deve operar com código antigo ainda não atualizado para java.time , converta para frente e para trás. Chame novos métodos de conversão adicionados às classes antigas. Para passar de umajava.util.Date
para umaInstant
, ligueDate::toInstant
.Período de tempo
As classes java.time dividiram essa ideia de representar um período de tempo como um número de anos, meses, dias, horas, minutos, segundos em duas metades:
Period
por anos, meses, diasDuration
por dias, horas, minutos, segundosAqui está um exemplo.
Despejar no console.
Ambos
Period
eDuration
usam o padrão ISO 8601 para gerar uma representação String de seu valor.O Java 9 inclui métodos para
Duration
obter a parte dos dias, parte das horas, parte dos minutos e parte dos segundos.Você pode obter o número total de dias ou horas ou minutos ou segundos ou milissegundos ou nanossegundos em toda a duração.
No Java 9, a
Duration
classe obtém novos métodos para retornar as várias partes de dias, horas, minutos, segundos, milissegundos / nanossegundos. Chamar osto…Part
métodos:toDaysPart()
,toHoursPart()
e assim por diante.ChronoUnit
Se você se importa apenas com uma granularidade de tempo maior e mais simples, como "número de dias decorridos", use a
ChronoUnit
enumeração.Outro exemplo.
Sobre java.time
A estrutura java.time é integrada ao Java 8 e posterior. Essas classes suplantar os velhos problemáticos legados aulas de data e hora, como
java.util.Date
,Calendar
, eSimpleDateFormat
.O projeto Joda-Time , agora em modo de manutenção , aconselha a migração para java.time.
Para saber mais, consulte o Tutorial do Oracle . E procure Stack Overflow para muitos exemplos e explicações. A especificação é JSR 310 .
Onde obter as classes java.time?
O projeto ThreeTen-Extra estende o java.time com classes adicionais. Este projeto é um campo de prova para possíveis adições futuras ao java.time. Você pode encontrar algumas classes úteis aqui, como
Interval
,YearWeek
,YearQuarter
, e mais .Joda-Time
ATUALIZAÇÃO: O projeto Joda-Time agora está no modo de manutenção , com a equipe aconselhando a migração para o java.time classes . Deixo esta seção intacta para a história.
A biblioteca Joda-Time usa a ISO 8601 para seus padrões. Sua
Period
classe analisa e gera essas seqüências PnYnMnDTnHnMnS.Renderiza:
fonte
Period
,Duration
eChronoUnit
, três classes, cujo propósito é determinar o delta entre pontos de tempo. Por favor, indique quais partes do meu "muro de texto" são irrelevantes. E você está incorreto ao dizer que a pergunta solicitou um "delta entre datas": a pergunta solicitou um delta entreDate
objetos, que são momentos de data e hora, e não "datas", apesar do nome infeliz dessa classe.java.util.Date
para umInstant
(apenas chame.toInstant
). E eu adicionei aMoment
seção para explicar. Você mencionou um par deDate
objetos, mas, na verdade, a Pergunta usa apenas um únicoDate
objeto existente e, em seguida, captura o momento atual, então fiz o mesmo. Obrigado pelo feedback! Dica: Desista de usarDate
- Essas classes herdadas são realmente uma bagunça terrível.https://www.joda.org/joda-time/faq.html#datediff
fonte
Uma alternativa um pouco mais simples:
Quanto a "melhor": bem, o que exatamente você precisa? O problema de representar durações de tempo como um número de horas e dias etc. é que isso pode levar a imprecisões e expectativas erradas devido à complexidade das datas (por exemplo, os dias podem ter 23 ou 25 horas devido ao horário de verão).
fonte
O uso da abordagem em milissegundos pode causar problemas em alguns locais.
Vamos considerar, por exemplo, que a diferença entre as duas datas 24/03/2007 e 25/03/2007 deve ser de 1 dia;
No entanto, usando a rota de milissegundos, você receberá 0 dias, se executar isso no Reino Unido!
A melhor maneira de implementar isso é usar java.util.Calendar
fonte
Há muitas maneiras de encontrar a diferença entre datas e horas. Uma das maneiras mais simples que conheço seria:
A declaração de impressão é apenas um exemplo - você pode formatá-la da maneira que desejar.
fonte
Como todas as respostas aqui estão corretas, mas usam java legado ou bibliotecas de terceiros, como joda ou similar, mostrarei outra maneira de usar as novas classes java.time no Java 8 e posterior. Consulte o Tutorial do Oracle .
Use
LocalDate
eChronoUnit
:fonte
Subtraindo as datas em milissegundos obras (como descrito em outro post), mas você tem de usar HOUR_OF_DAY e não HOUR ao limpar as partes de tempo das datas:
fonte
Se você não deseja usar o JodaTime ou similar, a melhor solução é provavelmente a seguinte:
O número de ms por dia nem sempre é o mesmo (devido ao horário de verão e segundos bissextos), mas é muito próximo e pelo menos os desvios devido ao horário de verão são cancelados por períodos mais longos. Portanto, dividir e arredondar fornecerá um resultado correto (pelo menos enquanto o calendário local usado não contiver saltos de tempo estranhos que não sejam o horário de verão e pular segundos).
Observe que isso ainda pressupõe isso
date1
edate2
está definido para a mesma hora do dia. Para diferentes horários do dia, você primeiro precisa definir o que significa "diferença de data", como apontado por Jon Skeet.fonte
date1.getTime()
vsdate2.getTime()
. Portanto, a diferença de 03/03/2016 para 31/03/2016 computará 27 dias enquanto você deseja 28 dias.Math.round()
isso parece seguro nos calendários do 'mundo real'. Desculpe pelo barulho.Dê uma olhada no Joda Time , que é uma API de Data / Hora aprimorada para Java e deve funcionar bem com o Scala.
fonte
Deixe-me mostrar a diferença entre Joda Interval e Days:
fonte
Se você precisar de uma String de retorno formatada como "2 dias 03h 42m 07s", tente o seguinte:
fonte
std
acima é indefinido.Nota: startDate e endDates são -> java.util.Date
e data final
Semelhante a dias, você também pode obter horas, minutos e segundos
fonte
Veja o exemplo aqui http://www.roseindia.net/java/beginners/DateDifferent.shtml Este exemplo fornece diferenças em dias, horas, minutos, segundos e milésimos de segundo :).
fonte
Use o fuso horário GMT para obter uma instância do calendário, defina o horário usando o método set da classe Calendar. O fuso horário GMT tem 0 deslocamento (não muito importante) e o sinalizador de horário de verão está definido como falso.
fonte
java.util.Date
etc. O uso do hack para definir o fuso horário como GMT torna o código insensível aos efeitos do horário de verão.O código a seguir pode fornecer a saída desejada:
fonte
fonte
fonte
Date
, portanto, essa comparação é a melhor que pode ser alcançada, dadas as circunstâncias.A melhor coisa a fazer é
Esse número é o número de milissegundos em um dia.
Uma data e outra data dão a diferença em milissegundos.
Colete a resposta em uma variável dupla .
fonte
Aqui está uma solução Java 7 correta em O (1) sem nenhuma dependência.
fonte
Essa é provavelmente a maneira mais direta de fazer isso - talvez porque eu esteja codificando em Java (com suas bibliotecas de datas e horas reconhecidamente desajeitadas) há algum tempo, mas esse código parece "simples e agradável" para mim!
Você está satisfeito com o resultado ser retornado em milissegundos ou faz parte da sua pergunta que você prefere que ele seja retornado em algum formato alternativo?
fonte
Não está usando a API padrão, não. Você pode rolar sozinho fazendo algo assim:
Ou você pode usar o Joda :
fonte
Apenas para responder à pergunta inicial:
Coloque o seguinte código em uma função como Long getAge () {}
O mais importante aqui é trabalhar com números longos ao multiplicar e dividir. E, claro, a compensação que o Java aplica no cálculo de datas.
:)
fonte
Como a pergunta está marcada com Scala,
fonte
Depois de pesquisar todas as outras respostas, para manter o tipo Java 7 Date, mas seja mais preciso / padrão com a abordagem do Java 8 diff,
fonte
tente isto:
você pode editar a string nos parâmetros dos métodos parse ().
fonte