Search code examples
javajava-11java-time

Using Java Time API to add temporal scalar to now and convert to Date


Java 11 here. I'm trying to take LocalDateTime.now() and add a certain number of mins (minToAdd) to it, and convert the result to a new Date that is my LocalDateTime.now() plus minsToAdd. I do not want to use Joda or any other library as I'm sure Java is perfectly capable of doing this for me. I would like to avoid using Calendar if at all possible, in lieu of LocalDateTime since that seems to be the new + recommended API.

My best attempt:

LocalDateTime nowLdt = LocalDateTime.now();
LocalDateTime expiryLdt = nowLdt.plusMinutes(minsToAdd);
Date expiry = Date.from(expiryLdt.toLocalDate().atStartOfDay(ZoneId.systemDefault()).toInstant());

This doesn't throw any errors but returns a Date that contains the current day's start of day (00:00:00) time component. Can anyone spot where I'm going awry? I just want Date that represents now + minsToAdd.


Solution

  • tl;dr

    Your Question is confused. But I am guessing that you want to know the calendar date of a moment several minutes from now, as seen through the JVM’s current default time zone.

    LocalDate ld =
        Instant
        .now()
        .plus( Duration.ofMinutes( someNumber ) )
        .atZone( ZoneId.systemDefault() )  // For any given moment, the date varies around the globe by time zone. 
        .toLocalDate()
    ;
    

    In contradiction, you also asked for:

    I just want Date that represents now + minsToAdd.

    java.util.Date utilDate = 
        java.util.Date
        .from(
            Instant
            .now()
            .plus( Duration.ofMinutes( someNumber ) )
        )
    ;
    

    Details

    I cannot imagine a situation where calling LocalDateTime.now is the right thing to do.

    The LocalDateTime class purposely lacks any concept of time zone or offset from UTC. So this class cannot represent a point on the timeline. A LocalDateTime instance is inherently ambiguous.

    To capture the current moment in UTC, use Instant.

    Instant now = Instant.now() ;
    

    If you want a moment a few minutes in the future, call plus.

    Duration d = Duration.ofMinutes( someNumber ) ;
    Instant later = now.plus( d ) ;
    

    Best to avoid java.util.Date. But if you must have an instance to interoperate with old code not yet updated to java.time, you can convert. Look to new conversion methods added to the legacy classes.

    java.util.Date utilDate = java.util.Date.from( later ) ;
    

    If your goal is to see the calendar date containing that later moment, specify a time zone (ZoneId) to determine a LocalDate object.

    ZoneId z = … ;  // If you want to use the JVM’s current default time zone: ZoneId.systemDefault()
    ZonedDateTime zdt = later.atZone( z ) ;
    LocalDate ld = later.toLocalDate() ;
    

    Avoid both Date classes. Along with Calendar, they are part of the terrible date-time classes that were years ago supplanted by the modern java.time classes.