首页 > 解决方案 > java.time: 比较两个 Instants - 获取两者之间的小时数、分钟数、秒数、年数、月数

问题描述

我试过这段代码:

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
    }
}

但是,然后该TimePassed对象将具有seconds = 6100and minutes = 101hours = 1而我希望它是hours = 1, minutes = 41, seconds = 40,所以60*60 + 41*60 + 40 = 6100. 可以用java.time包做吗?因为到目前为止,我只能通过秒、通过分钟或通过小时等。两者都不会考虑另一个。

标签: javadatetimeunix-timestamp

解决方案


Java 9 答案:Duration.toXxxPart 方法

基本思路,不完整:

    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

用与问题相距 6100 秒的瞬间进行测试。这些toXxxPart方法是在 Java 9 中引入的。对于 Java 8(或 ThreeTen Backport),您需要从较粗的单位开始,即天,然后从持续时间中减去它们,然后再获得下一个更精细的单位。有关示例,请参见lauhub 的此答案

不过,要完全正确,这些年和日子有点棘手。要仅获取超过全年的天数,请查看完整代码:

    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

我故意ZoneId.systemDefault()只阅读一次,以防万一有人更改正在进行的默认时区设置。


推荐阅读