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()
的方法,并手动将它们除以分钟数,例如每小时分钟数等: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
和noduration.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);