简体   繁体   中英

How to change time unit from seconds to days/months/years

I am bashing my head against Java's Temporal API. I can't find anything in the Java Docs or anywhere else that'll answer what I need to do. I simply need to at 1,000,000,000 seconds to a date and return the date, calculating the moment someone lived a billion seconds (somewhere around 30 years.)

    public Temporal getGigasecondDate(Temporal given) {
        final long gigasecond = 1000000000;
        final long gigaDays = gigasecond / 60 / 60 / 24;

        Duration amount = Duration.ofDays(gigaDays);

        Temporal date = amount.addTo(given);

        return date;
    }

I get an error saying Exception in thread "main" java.time.DateTimeException: Unit must be Years, Months or Days, but was Seconds and I can't for the life of me find a way in the JavaDocs, or anywhere else, figure out how to get the unit to years, months, or days.

All I need to do, is return a Temporal object that states the moment someone has lived a billion seconds.

tl;dr

ZonedDateTime.of(                         // Mom gave birth at 3 AM in year 2000, New Zealand time.
    2000 , 1 , 23 , 3 , 45 , 0 , 0 , ZoneId.of( "Pacific/Auckland" )  
)                                         // Returns a `ZonedDateTime` object.
.plus(
    Duration.ofSeconds( 1_000_000_000L )  // A billion seconds.
)                                         // Returns another `ZonedDateTime` object. Immutable objects in *java.time* means we get a fresh object rather than “mutating” (altering) the original.
.toString()                               // Generate a `String` representing the value of our `ZonedDateTime` object, using standard ISO 8601 format wisely extended to append the name of the time zone in square brackets. 

2031-10-01T05:31:40+13:00[Pacific/Auckland]

Details

The Answer by Andreas is correct. Here are a few more thoughts.

Do not use Temporal

The documentation for java.time explains that generally in an app you should be using the concrete classes rather than the interfaces and superclasses. To quote from Temporal interface:

This interface is a framework-level interface that should not be widely used in application code. Instead, applications should create and pass around instances of concrete types, such as LocalDate. There are many reasons for this, part of which is that implementations of this interface may be in calendar systems other than ISO. See ChronoLocalDate for a fuller discussion of the issues.

Adding a billion seconds to a birth-moment

[add] 1,000,000,000 seconds to a date and return the date,

Determine the moment of the person's birth.

LocalDate ld = LocalDate.of( 2000 , Month.JANUARY , 23 ) ;
LocalTime lt = LocalTime.of( 3 , 45 ) ;  // Mom gave birth at 3 AM in New Zealand time.
ZoneId z = ZoneId.of( "Pacific/Auckland" ) ;
ZonedDateTime zdt = ZonedDateTime.of( ld , lt , z ) ;

See that same moment in UTC, if useful.

Instant instant = zdt.toInstant() ;

Define the amount of time to add. The Duration class represents a span of time not attached to the timeline.

Duration d = Duration.ofSeconds( 1_000_000_000L ) ;  

Add.

ZonedDateTime zdtLater = zdt.plus( d ) ;

Or, in UTC (same moment, different wall-clock time).

Instant instantLater = instant.plus( d ) ;

See this code run live at IdeOne.com .

zdt.toString(): 2000-01-23T03:45+13:00[Pacific/Auckland]

instant.toString(): 2000-01-22T14:45:00Z

d.toString(): PT277777H46M40S

zdtLater.toString(): 2031-10-01T05:31:40+13:00[Pacific/Auckland]

instantLater.toString(): 2031-09-30T16:31:40Z

If you care for only the date, without the time-of-day and without the time zone, extract a LocalDate .

LocalDate ldLater = zdtLater.toLocalDate() ; 

You can call plus(long amountToAdd, TemporalUnit unit) , with unit as ChronoUnit.SECONDS :

public static Temporal getGigasecondDate(Temporal given) {
    return given.plus(1_000_000_000, ChronoUnit.SECONDS);
}

Test

System.out.println(getGigasecondDate(LocalDateTime.of(2000, 1, 1, 0, 0)));
System.out.println(getGigasecondDate(ZonedDateTime.of(2000, 1, 1, 0, 0, 0, 0, ZoneId.of("America/New_York"))));

Output

2031-09-09T01:46:40
2031-09-09T02:46:40-04:00[America/New_York]

So, someone born at midnight on Jan 1, 2000 will be 1 billion seconds old on Sep 9, 2031 at 1:46:40 AM, assuming no Daylight Savings Time.

If they lived in New York, it would be at 2:46:40 AM EDT.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM