Como obter a hora de início e a hora de término de um dia?
código como este não é preciso:
private Date getStartOfDay(Date date) {
Calendar calendar = Calendar.getInstance();
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH);
int day = calendar.get(Calendar.DATE);
calendar.set(year, month, day, 0, 0, 0);
return calendar.getTime();
}
private Date getEndOfDay(Date date) {
Calendar calendar = Calendar.getInstance();
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH);
int day = calendar.get(Calendar.DATE);
calendar.set(year, month, day, 23, 59, 59);
return calendar.getTime();
}
Não é preciso até o milissegundo.
Respostas:
tl; dr
Início do dia
Obtenha o comprimento total do hoje como visto em um fuso horário.
Utilizando a abordagem semi-aberta, onde o início é inclusivo e o final é exclusivo . Essa abordagem resolve a falha no seu código que falha em explicar o último segundo do dia.
Veja os mesmos momentos no UTC.
Se você deseja o dia inteiro de uma data como visto no UTC, e não no fuso horário, use
OffsetDateTime
.Esses
OffsetDateTime
objetos já estarão no UTC, mas você pode chamartoInstant
se precisar desses objetos que estão sempre no UTC, por definição.Dica: você pode estar interessado em adicionar a biblioteca ThreeTen-Extra ao seu projeto para usar sua
Interval
classe para representar esse par deInstant
objetos. Isto oferece classe métodos úteis para comparação, comoabuts
,overlaps
,contains
e muito mais.Meio aberto
A resposta do mprivat está correta. Seu argumento é não tentar obter o final de um dia, mas comparar com "antes do início do dia seguinte". Sua idéia é conhecida como a abordagem "semi-aberta", em que um período de tempo tem um começo inclusivo, enquanto o final é exclusivo .
Joda-Time 2.3 oferece um método para este mesmo fim, para obter primeiro momento do dia:
withTimeAtStartOfDay()
. Da mesma forma em java.timeLocalDate::atStartOfDay
,.Pesquise StackOverflow por "joda half-open" para ver mais discussões e exemplos.
Veja este post, Intervalos de tempo e outros intervalos devem estar semi-abertos , por Bill Schneider.
Evite classes de data e hora herdadas
As classes java.util.Date e .Calendar são notoriamente problemáticas. Evite-os.
Use as classes java.time . A estrutura java.time é o sucessor oficial da bem - sucedida biblioteca Joda-Time .
java.time
A estrutura java.time é integrada ao Java 8 e posterior. Portado para Java 6 e 7 no projeto ThreeTen-Backport , adaptado ao Android no projeto ThreeTenABP .
An
Instant
é um momento na linha do tempo no UTC com uma resolução de nanossegundos .Aplique um fuso horário para obter a hora do relógio de parede em alguma localidade.
Para obter o primeiro momento do dia, leia a
LocalDate
aula e seuatStartOfDay
método.Usando a abordagem semi-aberta, obtenha o primeiro momento do dia seguinte.
Atualmente, a estrutura java.time não possui uma
Interval
classe, conforme descrito abaixo para o Joda-Time. No entanto, o projeto ThreeTen-Extra estende o java.time com classes adicionais. Este projeto é o campo de prova para possíveis adições futuras ao java.time. Entre suas classes éInterval
. Construa umInterval
passando um par deInstant
objetos. Podemos extrair umInstant
de nossosZonedDateTime
objetos.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
.Para saber mais, consulte o Tutorial do Oracle . E procure Stack Overflow para muitos exemplos e explicações. A especificação é JSR 310 .
O projeto Joda-Time , agora em modo de manutenção , aconselha a migração para as classes java.time .
Você pode trocar objetos java.time diretamente com seu banco de dados. Use um driver JDBC compatível com JDBC 4.2 ou posterior. Não há necessidade de strings, não há necessidade de
java.sql.*
classes. O Hibernate 5 e o JPA 2.2 suportam java.time .Onde obter as classes java.time?
Joda-Time
ATUALIZAÇÃO: O projeto Joda-Time agora está no modo de manutenção e aconselha a migração para as classes java.time . Estou deixando esta seção intacta para a história.
Joda-Time tem três classes para representar um espaço de tempo de várias maneiras:
Interval
,Period
, eDuration
. UmInterval
tem um começo e um fim específicos na linha do tempo do Universo. Isso se encaixa em nossa necessidade de representar "um dia".Chamamos o método em
withTimeAtStartOfDay
vez de definir a hora do dia como zeros. Por causa do horário de verão e de outras anomalias, o primeiro momento do dia pode não ser00:00:00
.Exemplo de código usando o Joda-Time 2.3.
Se necessário, você pode converter para um java.util.Date.
fonte
LocalDateTime
Java 8
Atualização : Adicionei estes 2 métodos às minhas Java Utility Classes aqui
Está no Repositório Central do Maven em:
Java 7 e anteriores
Com o Apache Commons
Sem Apache Commons
fonte
getStartOfDay
deveria ser:LocalDateTime startOfDay = localDateTime.with(LocalTime.MIN);
Ou seja, LocalTime, não LocalDateTime.getEndOfDay(Date date)
.getStartOfDay(Date date)
Os métodos na seção Java 8 estão corretos, ou seja, LocalDateTime.MAX e .MIN, colocam você nas primeiras datas possíveis no passado e no futuro, não no início e no final de um dia. Em vez disso, sugiro .atStartOfDay () para start e .plusDays (1) .atStartOfDay (). MinusNanos (1) para end.localDateTimeToDate(LocalDateTime startOfDay)
throws Exception - java.lang.IllegalArgumentException: java.lang.ArithmeticException: long estouroem getEndOfDay, você pode adicionar:
Embora matematicamente falando, você não pode especificar o final de um dia a não ser dizendo que é "antes do início do dia seguinte".
Então, em vez de dizer,
if(date >= getStartOfDay(today) && date <= getEndOfDay(today))
você deve dizer:if(date >= getStartOfDay(today) && date < getStartOfDay(tomorrow))
. Essa é uma definição muito mais sólida (e você não precisa se preocupar com precisão de milissegundos).fonte
java.time
Usando a
java.time
estrutura incorporada no Java 8.fonte
Local…
classes não têm conceito de fuso horário e ajuste para anomalias. Por exemplo, alguns fusos horários têm uma alteração no horário de verão à meia-noite, portanto, o primeiro momento do dia é no horário01:00:00.0
(01:00) e não no00:00:00.0
valor produzido por esse código. Use emZonedDateTime
vez disso.Uma maneira adicional de encontrar o início do dia com java8 java.time.ZonedDateTime em vez de passar
LocalDateTime
é simplesmente truncar a entrada ZonedDateTime para DAYS:fonte
Para java 8, as seguintes instruções de linha única estão funcionando. Neste exemplo, eu uso o fuso horário UTC. Por favor, considere alterar o TimeZone usado atualmente.
Se não houver diferença horária com a saída. Experimentar:
ZoneOffset.ofHours(0)
fonte
toInstant
é sintaxe ilegal e redundante conceitualmente.Java 8 ou ThreeTenABP
ZonedDateTime
LocalDateTime
Espero que ajude alguém.
fonte
Eu tentei esse código e funciona bem!
fonte
ZonedDateTime
e estáInstant
à sua disposição, não há necessidade de usá-lojava.sql.Timestamp
. Essa classe é uma das terríveis e antigas classes herdadas agora substituídas pelas classes java.time . A partir do JDBC 4.2, podemos trocar diretamente objetos java.time com o banco de dados. Sua mistura do legado e das classes modernas não faz sentido para mim.Outra solução que não depende de nenhuma estrutura é:
Observe que ele retorna o horário com base no UTC
fonte
calendar.setTimeInMillis (0); fornece precisão de até milissegundos
fonte
Sei que é um pouco tarde, mas no caso do Java 8, se você estiver usando o OffsetDateTime (que oferece muitas vantagens, como TimeZone, Nanossegundos etc.), você pode usar o seguinte código:
fonte
Tive vários inconvenientes com todas as soluções, porque precisava do tipo de variável Instant e o fuso horário sempre interferia na mudança de tudo. Depois, combinando soluções, vi que essa é uma boa opção.
e nós temos como resultado
Espero que ajude você
fonte
Instant
objetos. Dica: você pode estar interessado em adicionar a biblioteca ThreeTen-Extra ao seu projeto para usar suaInterval
classe.Eu acho que o mais fácil seria algo como:
Esses milis podem ser convertidos em Calendário, Instant ou LocalDate conforme sua necessidade com o Joda Time.
fonte
fonte