Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/305.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java time:比较两个实例-获取两个实例之间的小时、分钟、秒、年、月数_Java_Datetime_Unix Timestamp - Fatal编程技术网

Java time:比较两个实例-获取两个实例之间的小时、分钟、秒、年、月数

Java time:比较两个实例-获取两个实例之间的小时、分钟、秒、年、月数,java,datetime,unix-timestamp,Java,Datetime,Unix Timestamp,我尝试了以下代码: 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();

我尝试了以下代码:

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=6100
minutes=101
hours=1
,而我希望它是
hours=1
minutes=41,seconds=40
,这样
60*60+41*60+40=6100
。可以使用
java.time
包吗?因为到目前为止,我只能获得秒数、分钟数或小时数等,而这两者都不能解释另一个。

Java 9答案:Duration.toxxpart方法 基本思想,不完整:

    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 seoncd。Java 9中引入了
toxxpart
方法。对于Java8(或ThreeTen Backport),您需要从较粗的单位开始,即天,然后从持续时间中减去它们,然后再获得下一个较细的单位。请参阅以获取示例

不过,要想完全正确,年份和天数有点棘手。要仅获取超过全年的天数,请参阅完整代码:

    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();
为什么/如何工作:

  • 非时间字段(年、月、日)中的差异是通过使用专门的
    期间
    类型来计算的,该类型正是用于此目的。它使用两个日期时间的
    LocalDate
    部分,这是安全的,因为它们都在同一时区
  • 为了了解其余字段的差异,我们调整了“
    ago
    ”值,使日期完全相同。如果我们发生了超调(如果“以前”发生在当地时间比“现在”更早,则可能发生超调),我们会通过将调整后的日期时间和周期减少一天来进行调整
  • 然后,我们使用
    Duration
    类来获得基于时间的字段之间的差异。因为我们在这里查询调整后的日期时间之间的差异,所以我们的持续时间不会超过一天,我为其添加了断言
  • 最后,我使用了
    Period
    Duration
    上可用的各种方法来获取它们的“字段”。请注意,我使用的
    Duration
    类的方法仅在Java 9之后可用,因此如果您还没有,则必须使用类似
    toMinutes()
    的方法,并手动将它们除以分钟数,例如每小时分钟数等:
  • 或者,如果您不想定义常量,可以通过调整“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);
    

    它不能按我需要的方式工作。例如,它输出
    seconds=118
    minutes=1
    ,而我需要它执行
    minutes=1;秒=58
    。我没有看到持续时间。toHoursPart方法,只有持续时间。toHours和持续时间。toSeconds。编辑:噢,Java9i编辑了一篇关于Java8的简短解释@解析我没有看到
    duration.toHoursPart
    方法,只有
    duration.toHours
    和no
    duration.toSeconds
    在all@parsecer,正如我提到的,这些都是添加到类中的,如果您仍然使用Java8,那么您必须编写粘合代码。这是一个很好的解释性解决方案。作为一个细节,我不一定确信您的
    断言在所有情况下都适用。当夏季(DST)结束时,一天可以是25小时。因此,我认为您的
    持续时间
    可能会结束,例如24小时30分钟,而
    持续时间
    将解释为1天30分钟。@OleV.V.,这可能是真的,我曾考虑过在接近过渡时这件事会如何表现,但尚未测试它。如果你说的是真的,那么断言是错的,但我不知道该给出哪个答案:处于过渡期是否意味着我们应该报告两个小时过去了,而大多数人认为这只是一个小时?编辑:据我记忆所及,在这些案例中,持续时间是“一小时过去了”,意思是史蒂文认为我们只是凡人,而这一断言可能根本没有错。Upd:当我说“史蒂文”时,我的意思是“史蒂文”,我的坏朋友。
    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);