I tried this code:
public class TimePassed {
private long seconds;
private long minutes;
private long hours;
private long days;
private long years;
...
public TimePassed(double unixSeconds) {
Instant now = Instant.now();
Instant ago = Instant.ofEpochSecond((long) unixSeconds);
this.seconds = ChronoUnit.SECONDS.between(
ago.atZone(ZoneId.systemDefault()),
now.atZone(ZoneId.systemDefault())); //6100
this.minutes = ChronoUnit.MINUTES.between(
ago.atZone(ZoneId.systemDefault()),
now.atZone(ZoneId.systemDefault())); //101
this.hours = ChronoUnit.HOURS.between(
ago.atZone(ZoneId.systemDefault()),
now.atZone(ZoneId.systemDefault())); //1
this.days = ChronoUnit.DAYS.between(
ago.atZone(ZoneId.systemDefault()),
now.atZone(ZoneId.systemDefault())); //0
this.years = ChronoUnit.YEARS.between(
ago.atZone(ZoneId.systemDefault()),
now.atZone(ZoneId.systemDefault())); //0
}
}
However then the TimePassed
object would have seconds = 6100
and minutes = 101
and hours = 1
, while I want it to be hours = 1
, minutes = 41, seconds = 40
, so that 60*60 + 41*60 + 40 = 6100
. Is it possible to do with java.time
package? Because as of now I can only either get passed seconds, passed minutes or passed hours, etc. And neither would account for the other.
Basic idea, not complete:
Duration dur = Duration.between(ago, now);
this.seconds = dur.toSecondsPart(); // 40
this.minutes = dur.toMinutesPart(); // 41
this.hours = dur.toHoursPart(); // 1
this.days = dur.toDaysPart(); // 0
Tested with instants that are 6100 seoncds apart like yours from the question. The toXxxPart
methods were introduced in Java 9. For Java 8 (or ThreeTen Backport) you will need to start from the coarser units, the days, and subtract them from the duration before getting the next finer unit. See this answer by lauhub for an example
The years and days are a bit tricky to get completely correct, though. To get only the days that exceed the whole years here’s the full code:
ZoneId zone = ZoneId.systemDefault();
ZonedDateTime agoZdt = ago.atZone(zone);
ZonedDateTime nowZdt = now.atZone(zone);
this.years = ChronoUnit.YEARS.between(agoZdt, nowZdt);
ZonedDateTime afterWholeYears = agoZdt.plusYears(this.years);
Duration dur = Duration.between(afterWholeYears, nowZdt);
this.seconds = dur.toSecondsPart(); // 40
this.minutes = dur.toMinutesPart(); // 41
this.hours = dur.toHoursPart(); // 1
this.days = dur.toDays(); // 0
I am on purpose reading ZoneId.systemDefault()
only once just for the unlikely case that someone changes the default time zone setting underway.