Java 8: 两个 LocalDateTime 之间多个单位的差异
Java 8: 两个 LocalDateTime 之间多个单位的差异
我正在尝试计算两个LocalDateTime之间的差异。\n输出需要以\"y years m months d days h hours m minutes s seconds\"的格式呈现。以下是我编写的代码:\n
import java.time.Duration; import java.time.Instant; import java.time.LocalDateTime; import java.time.Period; import java.time.ZoneId; public class Main { static final int MINUTES_PER_HOUR = 60; static final int SECONDS_PER_MINUTE = 60; static final int SECONDS_PER_HOUR = SECONDS_PER_MINUTE * MINUTES_PER_HOUR; public static void main(String[] args) { LocalDateTime toDateTime = LocalDateTime.of(2014, 9, 9, 19, 46, 45); LocalDateTime fromDateTime = LocalDateTime.of(1984, 12, 16, 7, 45, 55); Period period = getPeriod(fromDateTime, toDateTime); long time[] = getTime(fromDateTime, toDateTime); System.out.println(period.getYears() + " years " + period.getMonths() + " months " + period.getDays() + " days " + time[0] + " hours " + time[1] + " minutes " + time[2] + " seconds."); } private static Period getPeriod(LocalDateTime dob, LocalDateTime now) { return Period.between(dob.toLocalDate(), now.toLocalDate()); } private static long[] getTime(LocalDateTime dob, LocalDateTime now) { LocalDateTime today = LocalDateTime.of(now.getYear(), now.getMonthValue(), now.getDayOfMonth(), dob.getHour(), dob.getMinute(), dob.getSecond()); Duration duration = Duration.between(today, now); long seconds = duration.getSeconds(); long hours = seconds / SECONDS_PER_HOUR; long minutes = ((seconds % SECONDS_PER_HOUR) / SECONDS_PER_MINUTE); long secs = (seconds % SECONDS_PER_MINUTE); return new long[]{hours, minutes, secs}; } }
\n我得到的输出结果是\"29 years 8 months 24 days 12 hours 0 minutes 50 seconds\"。我已经从这个网站(使用值\"12/16/1984 07:45:55\"和\"09/09/2014 19:46:45\")验证了我的结果。以下是截图:\n\n我非常确定月份后面的字段在我的代码中是错误的。任何建议都将非常有帮助。\n
更新
\n我已经从另一个网站测试了我的结果,得到的结果是不同的。这是它:计算两个日期之间的时长(结果:29年8个月24天12小时0分钟50秒)。\n
更新
\n由于我从两个不同的网站得到了两个不同的结果,我想知道我的计算算法是否合法。如果我使用以下两个LocalDateTime对象:\n
LocalDateTime toDateTime = LocalDateTime.of(2014, 9, 10, 6, 40, 45); LocalDateTime fromDateTime = LocalDateTime.of(1984, 12, 16, 7, 45, 55);
\n那么输出结果是:\"29 years 8 months 25 days -1 hours -5 minutes -10 seconds.\"。\n从这个链接中应该是\"29 years 8 months 24 days 22 hours, 54 minutes and 50 seconds\"。所以算法需要处理负数。\n请注意,问题不是哪个网站给我什么结果,我需要知道正确的算法并得到正确的结果。
问题的出现原因:
在Java 8中,没有一个时间段(period)类可以跨越时间,因此需要自己进行计算。
解决方法:
幸运的是,日期和时间类有很多实用方法可以简化计算。以下是一种计算时间差的方法,虽然不一定是最快的方法:
LocalDateTime fromDateTime = LocalDateTime.of(1984, 12, 16, 7, 45, 55); LocalDateTime toDateTime = LocalDateTime.of(2014, 9, 10, 6, 40, 45); LocalDateTime tempDateTime = LocalDateTime.from( fromDateTime ); long years = tempDateTime.until( toDateTime, ChronoUnit.YEARS ); tempDateTime = tempDateTime.plusYears( years ); long months = tempDateTime.until( toDateTime, ChronoUnit.MONTHS ); tempDateTime = tempDateTime.plusMonths( months ); long days = tempDateTime.until( toDateTime, ChronoUnit.DAYS ); tempDateTime = tempDateTime.plusDays( days ); long hours = tempDateTime.until( toDateTime, ChronoUnit.HOURS ); tempDateTime = tempDateTime.plusHours( hours ); long minutes = tempDateTime.until( toDateTime, ChronoUnit.MINUTES ); tempDateTime = tempDateTime.plusMinutes( minutes ); long seconds = tempDateTime.until( toDateTime, ChronoUnit.SECONDS ); System.out.println( years + " years " + months + " months " + days + " days " + hours + " hours " + minutes + " minutes " + seconds + " seconds."); //输出结果:29 years 8 months 24 days 22 hours 54 minutes 50 seconds.
基本思路是这样的:创建一个临时的开始日期,获取到结束日期的完整年份。然后通过年数调整日期,使得开始日期距离结束日期不到一年。以此类推,依次处理每个时间单位。
最后需要说明的是,这个方法没有考虑不同的时区(两个日期应该在同一个时区),也没有测试/检查夏令时或其他日历变化(比如萨摩亚时区的变化)对计算的影响。所以请谨慎使用。
Java 8: 两个LocalDateTime之间的多个单位的差异
在Java 8中,我们可以使用ChronoUnit来计算两个LocalDateTime之间的差异。下面的代码展示了如何使用ChronoUnit来计算分钟和小时之间的差异:
long minutes = ChronoUnit.MINUTES.between(fromDate, toDate); long hours = ChronoUnit.HOURS.between(fromDate, toDate);
使用ChronoUnit进行日期差异计算的更多文档可以在这里找到:[Period and Duration](https://docs.oracle.com/javase/tutorial/datetime/iso/period.html)
然而,有一些人对这种方法表示了质疑。他们认为这种方法并没有真正改进。相较于Thomas的答案,只是将`tempDateTime.until( toDateTime, ChronoUnit.YEARS)`替换为`ChronoUnit.YEARS.between(fromDate, toDate)`。但是,重要的附加行,如`tempDateTime.plusYears( years )`等,在这个答案中完全缺失,因此对于提问者并没有真正帮助。完整的算法才是关键!
然而,还有一些人认为这种方法更简洁、更易读。他们认为这是找到两个日期之间差异的最佳方法。
对此,还有人提出异议,认为他们才是关键。提问者已经在一年多前得到了他们的答案。阅读此问题的36,000人并不关心提问者的具体问题。他们是通过谷歌搜索到这里的,而我的答案为他们提供了他们所寻找的干净简洁的解决方案,即计算两个日期之间的差异。
另外,有人认为许多人误解了问题。他们认为`ChronoUnit.between(...)`并不是什么新东西,可以在Stack Overflow上找到多次,例如:与JSR-310的主要作者的回答的示例链接
还有人分享了他们自己的解决方案,以获得两个日期时间之间的秒差异。他们表示自己的解决方案很复杂,于是上网搜索了解决方法。虽然satnam的答案可能并没有回答到提问者的问题,但对于他们和其他许多人来说,这确实帮了很大的忙。
总之,在这个问题中,有一些人认为ChronoUnit是计算两个LocalDateTime之间差异的最佳方法,而另一些人则认为这种方法并没有真正解决提问者的问题。不过,无论怎样,这个问题和讨论都为我们提供了不同的思考和学习的机会。