Compare LocalDateTime with long

299 Views Asked by At

I have a timestamp (ts1) stored in a long, expressed in nanos since epoch. I want to be able to compare it with another timestamp (ts2), which I know is for today 8am

The aim is to know if ts1 is after or before ts2.

I have ts2 as below:

LocalTime eight = LocalTime.of(8, 0);
LocalDate today = LocalDate.now(ZoneId.of("Europe/Milan"));
LocalDateTime ts2 = LocalDateTime.of(today, time);

How can I compare ts2 with ts1 which is a long?

3

There are 3 best solutions below

0
shmosel On BEST ANSWER

LocalDate and LocalDateTime are time zone agnostic. They only accept one in the now() factory to resolve the date in the specified zone, but then the time zone is discarded, so there's no way to convert it back to a particular timestamp. If you construct a ZonedDateTime instead, you can then adjust the time and extract the timestamp like this:

long ts2 = ZonedDateTime.now(ZoneId.of("Europe/Milan"))
        .withHour(8)
        .truncatedTo(ChronoUnit.HOURS)
        .toInstant()
        .toEpochMilli();
1
JavaMan On

You could use something like this

    Long ts1 = 123l;
    // Convert ts1 to an Instant
    long nanosInSecond = 1000000000L;
    Instant instantTs1 = Instant.ofEpochSecond(ts1 / nanosInSecond, ts1 % nanosInSecond);

    // Create ts2 from LocalDateTime
    LocalTime eight = LocalTime.of(8, 0);
    String zoneId = "Europe/Milan";
    LocalDate today = LocalDate.now(ZoneId.of(zoneId));
    LocalDateTime ts2 = LocalDateTime.of(today, eight);
    Instant instantTs2 = ts2.atZone(ZoneId.of(zoneId)).toInstant();

    
    if (instantTs1.isBefore(instantTs2)) {
        System.out.println("ts1 before ts2");
    } else if (instantTs1.isAfter(instantTs2)) {
        System.out.println("ts1 after ts2");
    } else {
        System.out.println("equal");
    }
4
Basil Bourque On

Comparing the current date & time in Milan with 8 AM today in Milan.

timestamp (ts1) stored in a long, expressed in nanos since epoch

Assuming you mean the epoch reference of first moment of 1970 in UTC, 1970-01-01T00:00Z, derive a Instant.

Instant instant = Instant.ofEpochSecond( 0 , myNanos ) ;

another timestamp (ts2), which I know is for today 8am

Determining "today" requires a time zone. For any given moment, both the date and time-of-day vary around the globe by time zone.

By the way, your Question’s time zone Europe/Milan does not exist. I don't know much about Italy, but I assume you really want Europe/Rome.

ZoneId z = ZoneId.of( "Europe/Rome" ) ;
ZonedDateTime nowInMilan = ZonedDateTime.now( z ) ;

We can move to another moment using the with method. Pass a LocalTime object for 8 AM. All parts of time-of-day will be replaced: hour, minute, second, & fractional second.

ZonedDateTime eightAmTodayInMilan = nowInMilan.with( LocalTime.of( 8 , 0 ) ) ;

compare it

You can compare moments using the isAfter, isBefore, and isEqual methods.

boolean nowIsAfter8AmInMilan = nowInMilan.isAfter( eightAmTodayInMilan ) ;

Alternatively, you could calculate elapsed time as a Duration. Then check if negative or positive.

Duration elapsed = Duration.between( eightAmTodayInMilan  , nowInMilan  ) ;
boolean nowIsBefore8AmInMilan = elapsed.isNegative() ;

LocalDateTime cannot represent a moment

The LocalDateTime represents a date with a time-of-day, no more, no less. This class purposely lacks any concept of time zone or offset-from-UTC.

Without the context of a zone/offset, an instance of LocalDateTime is inherently ambiguous. We don't know if noon on the 23rd of this January means noon in Tokyo, noon in Toulouse, or noon in Toledo Ohio US — three very different moments, each several hours apart.

For the problem stated in this Question, I would not involve LocalDateTime.

The Y2262 problem

I would suggest you find another way to represent a moment as a count of nanoseconds.

The main reason is that such a count is inherently ambiguous and error-prone. Since no human can read such a number as a date and time, logging and debugging are complicated.

Also, beware of the Y2262 problem. Assuming your epoch reference is first moment of 1970 in UTC, then counting nanos limits your future 2262-04-11T23:47:16.854775807Z. That is sufficient for current business purposes, but what if your app is still running in a few centuries?

Instant.EPOCH.plus( Duration.ofNanos( Long.MAX_VALUE ) )

Generally best to exchange date-time values as text in standard ISO 8601 format. Those formats are designed to be readable both by machine and by humans across cultures.