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 = 6100minutes = 101hours = 1,而我希望它是hours = 1minutes = 41,seconds = 40,这样60*60 + 41*60 + 40 = 6100。是否可以使用java.time软件包?因为到目前为止,我只能通过秒,通过分钟或通过小时,等等。两者都无法解决。

aabb5888157 回答:java.time:比较两个Instants-获得两者之间的小时数,分钟数,秒数,年数和月数

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),您需要从较粗的单位(天)开始,并从持续时间中减去它们,然后再得到下一个较细的单位。有关示例,请参见this answer by 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()一次,以防万一有人更改正在进行的默认时区设置。

,

类似的事情应该起作用:

ZoneId zone = ZoneId.systemDefault();

ZonedDateTime ago = ZonedDateTime.ofInstant(Instant.ofEpochSeconds(unixSeconds),zone);
ZonedDateTime now = ZonedDateTime.now(zone);

Period period = Period.between(ago.toLocalDate(),now.toLocalDate());

ZonedDateTime adjusted = ago.with(now.toLocalDate());
if (adjusted.isAfter(now)) {
    adjusted = adjusted.minusDays(1);
    period = period.minusDays(1);
}    

Duration duration = Duration.between(adjusted,now);
assert duration.toDaysPart() == 0;

years   = period.getYears();
months  = period.getMonths();
days    = period.getDays();
hours   = duration.toHoursPart();
minutes = duration.toMinutesPart();
seconds = duration.toSecondsPart();

为什么/如何工作:

  1. 通过使用专门的Period类型来计算非时间字段(年,月,日)之间的差异,该类型正是为此目的而设计的。它使用两个日期时间的LocalDate部分,这是安全的,因为它们都在同一时区
  2. 要了解其余字段的差异,我们调整了“ ago”值,以使日期完全相同。如果我们碰巧超调了(如果“ ago”发生在本地时间早于“ now”,那么可能会发生),我们通过将调整后的日期时间和期间都减少一天来进行调整
  3. 然后,我们使用Duration类来获取基于时间的字段之间的差异。由于在那里我们查询了调整后的日期时间之间的差异,因此我们的持续时间不会超过一天,为此我添加了断言。
  4. 最后,我在PeriodDuration上使用了各种可用的方法来获取其“字段”。请注意,我使用的Duration类方法自Java 9起才可用,因此,如果您还没有,就必须使用toMinutes()之类的方法,并手动将它们除以数量,例如每小时的分钟数,例如:
    // those constants you'll have to define on your own,shouldn't be hard
    hours = duration.toHours() % Constants.HOURS_PER_DAY;

或者,如果您不想定义常量,则可以通过调整“ ago”变量来重复该技巧:

adjusted = ago.with(now.toLocalDate());
if (adjusted.isAfter(now)) {
    adjusted = adjusted.minusDays(1);
    period = period.minusDays(1);
}
hours = HOURS.between(adjusted,now);
adjusted = adjusted.withHour(now.getHour());
if (adjusted.isAfter(now)) {
    adjusted = adjusted.minusHour(1);
    hours -= 1;
}

minutes = MINUTES.between(adjusted,now);
adjusted = adjusted.withMinute(now.getMinute());
if (adjusted.isAfter(now)) {
    adjusted = adjusted.minusMinutes(1);
    minutes -= 1;
}
seconds = SECONDS.between(adjusted,now);
本文链接:https://www.f2er.com/3149864.html

大家都在问