Eu gostaria de ter um método compareTo que ignore a parte do tempo de um java.util.Date. Eu acho que existem várias maneiras de resolver isso. Qual é a maneira mais simples?
Atualização: enquanto o Joda Time era uma boa recomendação na época, use a java.time
biblioteca do Java 8+, sempre que possível.
Minha preferência é usar o Joda Time, o que torna incrivelmente fácil:
DateTime first = ...;
DateTime second = ...;
LocalDate firstDate = first.toLocalDate();
LocalDate secondDate = second.toLocalDate();
return firstDate.compareTo(secondDate);
EDIT: Como observado nos comentários, se você usar DateTimeComparator.getDateOnlyInstance()
, é ainda mais simples :)
// TODO: consider extracting the comparator to a field.
return DateTimeComparator.getDateOnlyInstance().compare(first, second);
("Use o tempo de Joda" é a base de quase todas as perguntas de SO que perguntam sobre java.util.Date
ou java.util.Calendar
. É uma API completamente superior. Se você está fazendo algo significativo com datas / horas, deve realmente usá-lo, se puder.)
Se você for absolutamente forçado a usar a API interna, crie uma instância Calendar
com a data apropriada e usando o fuso horário apropriado. Em seguida, você pode definir cada campo em cada calendário de horas, minutos, segundos e milissegundos para 0 e comparar os tempos resultantes. Definitivamente nojento em comparação com a solução Joda :)
A parte do fuso horário é importante: java.util.Date
é sempre baseada no UTC. Na maioria dos casos em que tenho interesse em uma data, essa é uma data em um fuso horário específico . Que por si só forçará você a usarCalendar
Joda Time (a menos que você queira contabilizar o fuso horário, o que eu não recomendo.)
Referência rápida para desenvolvedores do Android
//Add joda library dependency to your build.gradle file
dependencies {
...
implementation 'joda-time:joda-time:2.9.9'
}
Código de exemplo (exemplo)
DateTimeComparator dateTimeComparator = DateTimeComparator.getDateOnlyInstance();
Date myDateOne = ...;
Date myDateTwo = ...;
int retVal = dateTimeComparator.compare(myDateOne, myDateTwo);
if(retVal == 0)
//both dates are equal
else if(retVal < 0)
//myDateOne is before myDateTwo
else if(retVal > 0)
//myDateOne is after myDateTwo
O Apache commons-lang é quase onipresente. E daí?
fonte
Se você realmente deseja usar o java.util.Date, faça algo assim:
ou, em vez disso, usando um calendário (preferível, pois getYear () e outros itens obsoletos)
fonte
Minha preferência seria usar a biblioteca Joda
java.util.Date
diretamente, já que Joda faz uma distinção entre data e hora (consulte YearMonthDay e DateTime classes ).No entanto, se você deseja usar
java.util.Date
, sugiro escrever um método utilitário; por exemplofonte
Alguma opinião sobre essa alternativa?
fonte
==
operador não retorna necessariamentetrue
para Strings equivalentes (usoequals()
). Você certamente também não pode usar os outros operadores de comparação mencionados.sdf.format(date1).compareTo(sdf.format(date2));
.Se você deseja comparar apenas o mês, dia e ano de duas datas, o código a seguir funciona para mim:
Obrigado Rob.
fonte
Eu também prefiro o Joda Time , mas aqui está uma alternativa:
EDITAR
Coloquei o UTC abaixo, caso você precise comparar datas para um fuso horário específico que não seja o UTC. Se você tem essa necessidade, no entanto, eu realmente recomendo ir para Joda.
fonte
Math.abs(second.getTime() - first.getTime()) < 1000L*60*60*24
< oneDay
.tl; dr
Evite classes de data e hora herdadas
Evite as classes de data e hora antigas e problemáticas, como
Date
&Calendar
, agora suplantadas pelas classes java.time.Usando java.time
A
java.util.Date
representa um momento na linha do tempo no UTC. O equivalente em java.time éInstant
. Você pode converter usando novos métodos adicionados à classe herdada.Você deseja comparar por data. Um fuso horário é crucial para determinar uma data. Por um determinado momento, a data varia em todo o mundo por zona. Por exemplo, alguns minutos depois da meia-noite em Paris, a França é um novo dia, enquanto ainda é "ontem" em Montreal, no Quebec .
Especifique um nome próprio fuso horário no formato
continent/region
, comoAmerica/Montreal
,Africa/Casablanca
, ouPacific/Auckland
. Nunca utilize o 3-4 letras, comoEST
ouIST
como eles são não zonas verdadeiros tempo, não padronizados, e nem mesmo única (!).Aplique o
ZoneId
aoInstant
para obter umZonedDateTime
.A
LocalDate
classe representa um valor somente de data, sem hora do dia e sem fuso horário. Podemos extrair aLocalDate
de aZonedDateTime
, eliminando efetivamente a parte da hora do dia.Agora compare, usando métodos como
isEqual
,isBefore
, eisAfter
.Veja este código executado ao vivo em IdeOne.com .
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 o java.time classes .
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 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 .fonte
O apache commons-utils já mencionado :
fornece a você o objeto Date que contém apenas data, sem hora, e você pode compará-lo com
Date.compareTo
fonte
Receio que não exista um método de comparar duas datas que possam ser chamadas de "fácil" ou "simples".
Ao comparar duas instâncias de tempo com qualquer tipo de precisão reduzida (por exemplo, apenas comparar datas), você sempre deve levar em consideração como o fuso horário afeta a comparação.
If
date1
está especificando um evento que ocorreu no fuso horário +2 edate2
especificando um evento que ocorreu na EST, por exemplo, você deve ter o cuidado de entender corretamente as implicações da comparação.Seu objetivo é descobrir se os dois eventos ocorreram na mesma data do calendário em seus respectivos fusos horários? Ou Você precisa saber se as duas datas se enquadram na mesma data do calendário em um fuso horário específico (UTC ou sua TZ local, por exemplo).
Depois de descobrir o que realmente está tentando comparar, é apenas uma questão de triplicar a data do ano-mês em um fuso horário apropriado e fazer a comparação.
O tempo de Joda pode fazer com que a operação de comparação real pareça muito mais limpa, mas a semântica da comparação ainda é algo que você precisa descobrir por si mesmo.
fonte
Se você estiver usando Java 8, use as
java.time.*
classes para comparar datas - é preferível às váriasjava.util.*
classespor exemplo; https://docs.oracle.com/javase/8/docs/api/java/time/LocalDate.html
fonte
Se você deseja comparar apenas duas datas sem tempo, o código a seguir pode ajudá-lo:
fonte
Aqui está uma solução deste blog: http://brigitzblog.blogspot.com/2011/10/java-compare-dates.html
ou seja, você pode ver se a diferença horária em milissegundos é menor que a duração de um dia.
fonte
`
`
fonte
Eu não sei, é novo pensamento ou então, mas eu mostro a você como eu fiz
fonte
Basta marcar DAY_OF_YEAR em combinação com a propriedade YEAR
EDITAR:
Agora podemos usar o poder das funções de extensão Kotlin
fonte
No Java 8, você pode usar o LocalDate, que é muito semelhante ao do Joda Time.
fonte
Isso o ajudará a comparar datas sem considerar a hora.
fonte
Usando o getDateInstance de SimpleDateFormat, podemos comparar apenas dois objetos de data sem hora. Execute o código abaixo.
fonte
Usando http://mvnrepository.com/artifact/commons-lang/commons-lang
fonte
DateUtils.isSameDay(date1, date2)
.Outro método simples de comparação com base nas respostas aqui e na orientação do meu mentor
EDIT : De acordo com @ Jonathan Drapeau, o código acima falhou em alguns casos (eu gostaria de ver esses casos, por favor) e ele sugeriu o seguinte como eu entendo:
Observe que a classe Date está obsoleta porque não foi passível de internacionalização. A classe Calendar é usada em seu lugar!
fonte
getXxx
métodos obsoletos deDate
.Primeiro, lembre-se de que esta operação depende do fuso horário. Portanto, escolha se deseja fazê-lo no UTC, no fuso horário do computador, no seu fuso horário favorito ou onde. Se você ainda não está convencido de que isso é importante, veja meu exemplo na parte inferior desta resposta.
Como sua pergunta não é clara sobre isso, suponho que você tenha uma classe com um campo de instância representando um ponto no tempo e a implementação
Comparable
, e deseje que a ordem natural de seus objetos seja a data, mas não a hora , desse campo. Por exemplo:java.time
Classes Java 8Tomei a liberdade de alterar o tipo do seu campo de instância de
Date
paraInstant
, a classe correspondente no Java 8. Prometo retornar ao tratamentoDate
abaixo. Também adicionei uma constante de fuso horário. Você pode configurá-lo comoZoneOffset.UTC
ouZoneId.of("Europe/Stockholm")
o que achar apropriado (configurá-lo como umZoneOffset
trabalho porqueZoneOffset
é uma subclasse deZoneId
).Eu escolhi mostrar a solução usando as classes Java 8. Você pediu a maneira mais simples, certo? :-) Aqui está o
compareTo
método que você pediu:Se você nunca precisa a parte da hora
when
, é claro que é mais fácil para declararwhen
umLocalDate
e ignorar todas as conversões. Então não precisamos mais nos preocupar com o fuso horário.Agora, suponha que, por algum motivo, você não possa declarar seu
when
campoInstant
ou deseja mantê-lo antiquadoDate
. Se você ainda pode usar o Java 8, basta convertê-lo emInstant
e faça como antes:Da mesma forma para
o.when
.No Java 8?
Se você não pode usar o java 8, há duas opções:
Calendar
ouSimpleDateFormat
.Os modos antiquados
A resposta de Adamski mostra como tirar a parte do tempo
Date
daCalendar
aula. Eu sugiro que você usegetInstance(TimeZone)
para obter aCalendar
instância para o fuso horário desejado. Como alternativa, você pode usar a ideia da segunda metade da resposta de Jorn .Usar
SimpleDateFormat
é realmente uma maneira indireta de usar,Calendar
pois aSimpleDateFormat
contém umCalendar
objeto. No entanto, você pode achar menos problemático do que usarCalendar
diretamente:Isso foi inspirado na resposta de Rob .
Dependência de fuso horário
Por que precisamos escolher um fuso horário específico? Digamos que queremos comparar duas vezes que no UTC são 24 de março às 0:00 (meia-noite) e 12:00 (meio-dia). Se você fizer isso na CET (digamos, Europa / Paris), são 1 e 13 do dia 24 de março, ou seja, a mesma data. Em Nova York (horário de verão do leste), são 20:00 em 23 de março e 8:00 em 24 de março, ou seja, não é a mesma data. Portanto, faz diferença o fuso horário escolhido. Se você apenas confiar no padrão do computador, poderá ter surpresas quando alguém tentar executar seu código em um computador em outro lugar neste mundo globalizado.
Ligação
Link para o ThreeTen Backport, o backport das classes de data e hora do Java 8 para Java 6 e 7: http://www.threeten.org/threetenbp/ .
fonte
Minha proposição:
fonte
Usando o Apache commons, você pode:
fonte
esta é a maneira mais simples de resolver esse problema.
fonte
Resolvi isso comparando com carimbo de data e hora:
Evito usar o Joda Time porque no Android ocupa um espaço enorme. Tamanho importa. ;)
fonte
Outra solução usando Java 8 e Instant, está usando o método truncatedTo
Exemplo:
fonte
fonte
Isto é o que funcionou para mim:
fonte
Que tal
DateUtil.daysBetween()
. É Java e retorna um número (diferença em dias).fonte