塔帕斯玻色码和托马斯码存在一些问题。如果time differenс为负值,则array获得负值。例如,如果
LocalDateTime toDateTime = LocalDateTime.of(2014, 9, 10, 6, 46, 45);
LocalDateTime fromDateTime = LocalDateTime.of(2014, 9, 9, 7, 46, 45);
它返回0年0月1天-1小时0分0秒。
我认为正确的输出是:0年0月0天23小时0分0秒。
我建议在LocalDate和LocalTime实例上分离LocalDateTime实例。之后,我们可以获得Java 8 Period和Duration实例。Duration实例根据天数和全天时间值(< 24h)进行分离,并对周期值进行后续更正。当第二个LocalTime值在第一个LocalTime值之前时,需要将周期缩短一天。
下面是我计算LocalDateTime差异的方法:
private void getChronoUnitForSecondAfterFirst(LocalDateTime firstLocalDateTime, LocalDateTime secondLocalDateTime, long[] chronoUnits) {
/*Separate LocaldateTime on LocalDate and LocalTime*/
LocalDate firstLocalDate = firstLocalDateTime.toLocalDate();
LocalTime firstLocalTime = firstLocalDateTime.toLocalTime();
LocalDate secondLocalDate = secondLocalDateTime.toLocalDate();
LocalTime secondLocalTime = secondLocalDateTime.toLocalTime();
/*Calculate the time difference*/
Duration duration = Duration.between(firstLocalDateTime, secondLocalDateTime);
long durationDays = duration.toDays();
Duration throughoutTheDayDuration = duration.minusDays(durationDays);
Logger.getLogger(PeriodDuration.class.getName()).log(Level.INFO,
"Duration is: " + duration + " this is " + durationDays
+ " days and " + throughoutTheDayDuration + " time.");
Period period = Period.between(firstLocalDate, secondLocalDate);
/*Correct the date difference*/
if (secondLocalTime.isBefore(firstLocalTime)) {
period = period.minusDays(1);
Logger.getLogger(PeriodDuration.class.getName()).log(Level.INFO,
"minus 1 day");
}
Logger.getLogger(PeriodDuration.class.getName()).log(Level.INFO,
"Period between " + firstLocalDateTime + " and "
+ secondLocalDateTime + " is: " + period + " and duration is: "
+ throughoutTheDayDuration
+ "\n-----------------------------------------------------------------");
/*Calculate chrono unit values and write it in array*/
chronoUnits[0] = period.getYears();
chronoUnits[1] = period.getMonths();
chronoUnits[2] = period.getDays();
chronoUnits[3] = throughoutTheDayDuration.toHours();
chronoUnits[4] = throughoutTheDayDuration.toMinutes() % 60;
chronoUnits[5] = throughoutTheDayDuration.getSeconds() % 60;
}
上述方法可用于计算任何本地日期和时间值的差值,例如:
public long[] getChronoUnits(String firstLocalDateTimeString, String secondLocalDateTimeString) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime firstLocalDateTime = LocalDateTime.parse(firstLocalDateTimeString, formatter);
LocalDateTime secondLocalDateTime = LocalDateTime.parse(secondLocalDateTimeString, formatter);
long[] chronoUnits = new long[6];
if (secondLocalDateTime.isAfter(firstLocalDateTime)) {
getChronoUnitForSecondAfterFirst(firstLocalDateTime, secondLocalDateTime, chronoUnits);
} else {
getChronoUnitForSecondAfterFirst(secondLocalDateTime, firstLocalDateTime, chronoUnits);
}
return chronoUnits;
}
为上述方法编写单元测试很方便(它们都是PeriodDuration类成员)。代码如下:
@RunWith(Parameterized.class)
public class PeriodDurationTest {
private final String firstLocalDateTimeString;
private final String secondLocalDateTimeString;
private final long[] chronoUnits;
public PeriodDurationTest(String firstLocalDateTimeString, String secondLocalDateTimeString, long[] chronoUnits) {
this.firstLocalDateTimeString = firstLocalDateTimeString;
this.secondLocalDateTimeString = secondLocalDateTimeString;
this.chronoUnits = chronoUnits;
}
@Parameters
public static Collection<Object[]> periodValues() {
long[] chronoUnits0 = {0, 0, 0, 0, 0, 0};
long[] chronoUnits1 = {0, 0, 0, 1, 0, 0};
long[] chronoUnits2 = {0, 0, 0, 23, 0, 0};
long[] chronoUnits3 = {0, 0, 0, 1, 0, 0};
long[] chronoUnits4 = {0, 0, 0, 23, 0, 0};
long[] chronoUnits5 = {0, 0, 1, 23, 0, 0};
long[] chronoUnits6 = {29, 8, 24, 12, 0, 50};
long[] chronoUnits7 = {29, 8, 24, 12, 0, 50};
return Arrays.asList(new Object[][]{
{"2015-09-09 21:46:44", "2015-09-09 21:46:44", chronoUnits0},
{"2015-09-09 21:46:44", "2015-09-09 22:46:44", chronoUnits1},
{"2015-09-09 21:46:44", "2015-09-10 20:46:44", chronoUnits2},
{"2015-09-09 21:46:44", "2015-09-09 20:46:44", chronoUnits3},
{"2015-09-10 20:46:44", "2015-09-09 21:46:44", chronoUnits4},
{"2015-09-11 20:46:44", "2015-09-09 21:46:44", chronoUnits5},
{"1984-12-16 07:45:55", "2014-09-09 19:46:45", chronoUnits6},
{"2014-09-09 19:46:45", "1984-12-16 07:45:55", chronoUnits6}
});
}
@Test
public void testGetChronoUnits() {
PeriodDuration instance = new PeriodDuration();
long[] expResult = this.chronoUnits;
long[] result = instance.getChronoUnits(this.firstLocalDateTimeString, this.secondLocalDateTimeString);
assertArrayEquals(expResult, result);
}
}
无论第一个LocalDateTime值是否在任何LocalTime值之前或之前,所有测试都是成功的。