LocalDate
only has the date (day, month and year) and LocalDateTime
has the date and time. To make the conversion, you need to set the time that will be used. Some examples:
LocalDate data = LocalDate.of(2018, Month.SEPTEMBER, 17);
// seta o horário para 10:30
LocalDateTime dt = data.atTime(10, 30);
// seta o horário para 10:30:45
LocalDateTime dt = data.atTime(10, 30, 45);
// seta o horário para 10:30:45.123
LocalDateTime dt = data.atTime(10, 30, 45, 123000000);
The API has nanosecond accuracy, which means it is possible to have up to 9 decimal places in the fraction of seconds:
// seta o horário para 10:30:45.123456789
LocalDateTime dt = data.atTime(10, 30, 45, 123456789);
In the case of a search filter, it is common for the start date to be set to midnight and the end date to 23:59:59.999 (to make sure you will consider all day in the search).
So you could do:
filtro.setPeriodoDe(LocalDate.of(2018, Month.SEPTEMBER, 17).atStartOfDay());
filtro.setPeriodoAte(LocalDate.of(2018, Month.SEPTEMBER, 21).atTime(LocalTime.MAX));
atStartOfDay()
Arrow the time to midnight. And LocalTime.MAX
is a constant that is worth 23:59:59.999999999
.
Timezones and daylight saving time
Just remembering that LocalDateTime
does not have Timezone, so does not take into account the effects of daylight saving time, for example.
In this case, you would need a ZonedDateTime
, and for that would need to define a Timezone as well:
// seta o horário para 10:30 no timezone America/Sao_Paulo
ZonedDateTime zdt = data.atTime(10, 30).atZone(ZoneId.of("America/Sao_Paulo"));
// seta o horário para início do dia no timezone America/Sao_Paulo
ZonedDateTime zdt = data.atStartOfDay(ZoneId.of("America/Sao_Paulo"));
An example is when summer time begins in Brazil: at midnight the clock is early to 01:00. That means that on this day, all times between 00:00 and 00:59 do not exist in this Timezone. atStartOfDay(ZoneId)
already check this and arrow the time to 01:00, which is the first valid time in this case.
Already to get the end of the day, it’s a little more complicated. When summer time ends in Brazil, for example: at midnight the clock is set back an hour, back to 23:00. This means that all times between 23:00 and 23:59 are 2 times on this day (one on daylight saving time and the other on "normal time").
So set the time to LocalTime.MAX
in a ZonedDateTime
not always going to work. The most guaranteed way is to get the start of the next day and subtract 1 nanosecond. Thus, you have the last moment of the day, on Timezone, no matter what daylight saving time changes you may have.
// seta o horário para o final do dia no timezone America/Sao_Paulo
ZonedDateTime zdt = data
// início do dia seguinte no timezone
.plusDays(1).atStartOfDay(ZoneId.of("America/Sao_Paulo"))
// menos 1 nanossegundo
.minusNanos(1);
The name of Timezone (America/Sao_Paulo
) is part of the list of timezones defined by IANA. You can get the list of all available using ZoneId.getAvailableZoneIds()
. It is also possible to use Timezone default jvm using ZoneId.systemDefault()
.
Of course then you would have to change your search to use ZonedDateTime
, but that is up to you whether you will consider the effects of daylight saving or not.
I just have doubts if this works when daylight saving time starts or ends or when there is a change of time zone (I don’t know, I’ll do some tests). But anyway your answer is very good.
– Victor Stafusa
@Victorstafusa
LocalDateTime
do not take into account daylight saving or any timezone rules. I updated the answer, thanks!– hkotsubo
Was excellent!
– Victor Stafusa