Java 8:计算两个LocalDateTime之间的差异

时间:2022-11-12 12:10:43

I am trying to calculate the difference between two LocalDateTime.

我正在尝试计算两个LocalDateTime之间的差异。

The output needs to be of the format y years m months d days h hours m minutes s seconds. Here is what I have written:

输出的格式为y年m月d天h小时m分钟s秒。以下是我写的:

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};
    }
}

The output that I am getting is 29 years 8 months 24 days 12 hours 0 minutes 50 seconds. I have checked my result from this website (with values 12/16/1984 07:45:55 and 09/09/2014 19:46:45). The following screenshot shows the output:

我得到的输出是29年8个月24天12小时0分钟50秒。我已经在这个网站上查看了我的结果(数值为12/16/1984 07:45:55和09/09:2014 19:46:45)。下面的截图显示了输出:

Java 8:计算两个LocalDateTime之间的差异

I am pretty sure that the fields after the month value is coming wrong from my code. Any suggestion would be very helpful.

我很确定,月值之后的字段来自我的代码。任何建议都很有帮助。

Update

I have tested my result from another website and the result I got is different. Here it is: Calculate duration between two dates (result: 29 years, 8 months, 24 days, 12 hours, 0 minutes and 50 seconds).

我在另一个网站上测试了我的结果,结果是不同的。计算两个日期之间的持续时间(结果:29年,8个月,24天,12小时,0分钟50秒)。

Update

Since I got two different results from two different sites, I am wondering if the algorithm of my calculation is legitimate or not. If I use following two LocalDateTime objects:

由于我从两个不同的站点得到了两个不同的结果,我想知道我的计算算法是否合理。如果我使用以下两个LocalDateTime对象:

LocalDateTime toDateTime = LocalDateTime.of(2014, 9, 10, 6, 40, 45);
LocalDateTime fromDateTime = LocalDateTime.of(1984, 12, 16, 7, 45, 55);

Then the output is coming: 29 years 8 months 25 days -1 hours -5 minutes -10 seconds.

然后输出是29年8个月25天-1小时-5分钟-10秒。

From this link it should be 29 years 8 months 24 days 22 hours, 54 minutes and 50 seconds. So the algorithm needs to handle the negative numbers too.

从这个链接应该是29年8个月24天22小时54分钟50秒。所以算法也需要处理负数。

Note the question is not about which site gave me what result, I need to know the right algorithm and need to have right results.

注意,问题不在于哪个网站给了我什么结果,我需要知道正确的算法,需要有正确的结果。

6 个解决方案

#1


84  

Unfortunately there doesn't seem to be a period class that spans time as well, so you might have to do the calculations on your own.

不幸的是,似乎没有一个周期类也跨越时间,所以你可能需要自己计算。

Forunately the date and time classes have a lot of utility methods that simplify that to some degree. Here's a way to calculate the difference although not necessarily the fastest:

通常,日期和时间类有很多实用的方法可以在一定程度上简化它。这里有一种计算差异的方法,虽然不一定是最快的:

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.");

//prints: 29 years 8 months 24 days 22 hours 54 minutes 50 seconds.

The basic idea is this: create a temporary start date and get the full years to the end. Then adjust that date by the number of years so that the start date is less then a year from the end. Repeat that for each time unit in descending order.

最基本的想法是:创建一个临时的开始日期,并将其持续到年底。然后根据年数调整这个日期,以便从年底开始的日期少于一年。按降序对每个时间单元重复上述操作。

Finally a disclaimer: I didn't take different timezones into account (both dates should be in the same timezone) and I also didn't test/check how daylight saving time or other changes in a calendar (like the timezone changes in Samoa) affect this calculation. So use with care.

最后一个声明:我没有考虑不同的时区(两个日期都应该在同一个时区),也没有测试/检查日光节约时间或日历中的其他更改(比如萨摩亚的时区更改)是如何影响这个计算的。所以请小心使用。

#2


280  

I found the best way to do this is with ChronoUnit.

我发现最好的方法是用ChronoUnit。

long minutes = ChronoUnit.MINUTES.between(fromDate, toDate);
long hours = ChronoUnit.HOURS.between(fromDate, toDate);

Additional documentation is here: https://docs.oracle.com/javase/tutorial/datetime/iso/period.html

其他文档如下:https://docs.oracle.com/javase/tutorial/datetime/iso/period.html

#3


12  

Here a single example using Duration and TimeUnit to get 'hh:mm:ss' format.

这里有一个例子,使用持续时间和时间单位来获得“hh:mm:ss”格式。

                Duration dur = Duration.between(LocalDateTimeIni, LocalDateTimeEnd);
                long millis = dur.toMillis();

                String.format("%02d:%02d:%02d", 
                        TimeUnit.MILLISECONDS.toHours(millis),
                        TimeUnit.MILLISECONDS.toMinutes(millis) - 
                        TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millis)),
                        TimeUnit.MILLISECONDS.toSeconds(millis) - 
                        TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis)));

#4


4  

And the version of @Thomas in Groovy with takes the desired units in a list instead of hardcoding the values. This implementation (which can easily ported to Java - I made the function declaration explicit) makes Thomas approach more reuseable.

Groovy中的@Thomas版本在列表中获取所需的单元,而不是硬编码值。这个实现(可以很容易地移植到Java -我使函数声明显式)使Thomas方法更可重用。

def fromDateTime = LocalDateTime.of(1968, 6, 14, 0, 13, 0)
def toDateTime = LocalDateTime.now()
def listOfUnits = [
    ChronoUnit.YEARS, ChronoUnit.MONTHS, ChronoUnit.DAYS,
    ChronoUnit.HOURS, ChronoUnit.MINUTES, ChronoUnit.SECONDS,
    ChronoUnit.MILLIS]

println calcDurationInTextualForm(listOfUnits, fromDateTime, toDateTime)    

String calcDurationInTextualForm(List<ChronoUnit> listOfUnits, LocalDateTime ts, LocalDateTime to)
{
    def result = []

    listOfUnits.each { chronoUnit ->
        long amount = ts.until(to, chronoUnit)
        ts = ts.plus(amount, chronoUnit)

        if (amount) {
            result << "$amount ${chronoUnit.toString()}"
        }
    }

    result.join(', ')
}

At the time of this writing,the code above returns 47 Years, 8 Months, 9 Days, 22 Hours, 52 Minutes, 7 Seconds, 140 Millis. And, for @Gennady Kolomoets input, the code returns 23 Hours.

在撰写本文时,上述代码将返回47年、8个月、9天、22小时、52分钟、7秒、140米。对于@Gennady Kolomoets输入,代码返回23小时。

When you provide a list of units it must be sorted by size of the units (biggest first):

当你提供一个单位列表时,它必须按单位的大小排序(最大的优先):

def listOfUnits = [ChronoUnit.WEEKS, ChronoUnit.DAYS, ChronoUnit.HOURS]
// returns 2495 Weeks, 3 Days, 8 Hours

#5


2  

There is some problem for Tapas Bose code and Thomas code. If time differenсe is negative, array gets the negative values. For example if

Tapas Bose代码和Thomas代码存在一些问题。如果时间differenсe是负的,数组的负值。例如,如果

LocalDateTime toDateTime = LocalDateTime.of(2014, 9, 10, 6, 46, 45);
LocalDateTime fromDateTime = LocalDateTime.of(2014, 9, 9, 7, 46, 45);

it returns 0 years 0 months 1 days -1 hours 0 minutes 0 seconds.

它返回0年0月1天-1小时0分钟0秒。

I think the right output is: 0 years 0 months 0 days 23 hours 0 minutes 0 seconds.

我认为正确的输出是:0年0月0天23小时0分钟0秒。

I propose to separate the LocalDateTime instances on LocalDate and LocalTime instances. After that we can obtain the Java 8 Period and Duration instances. The Duration instance is separated on the number of days and throughout-the-day time value (< 24h) with subsequent correction of the period value. When the second LocalTime value is before the firstLocalTime value, it is necessary to reduce the period for one day.

我建议在LocalDate和LocalTime实例上分离LocalDateTime实例。之后,我们可以获得Java 8周期和持续时间实例。持续时间的实例在天数和每天的时间值(< 24h)之间进行分离,并随后对周期值进行修正。当第二个LocalTime值在第一个LocalTime值之前,有必要减少一天的时间。

Here's my way to calculate the LocalDateTime difference:

下面是我计算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;
}

The above method can be used to calculate the difference of any local date and time values, for example:

上述方法可用于计算任何本地日期和时间值的差异,例如:

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;
}

It is convenient to write a unit test for the above method (both of them are PeriodDuration class members). Here's the code:

为上述方法编写单元测试非常方便(它们都是周期化类成员)。这是代码:

@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);
}

}

}

All tests are successful whether or not the value of the first LocalDateTime is before and for any LocalTime values.

无论第一个LocalDateTime的值是之前还是任何LocalTime值,所有测试都是成功的。

#6


0  

Here is a very simple answer to your question. It works.

这里有一个非常简单的答案来回答你的问题。它的工作原理。

import java.time.*;
import java.util.*;
import java.time.format.DateTimeFormatter;
public class MyClass {
    public static void main(String args[]) {
       DateTimeFormatter T = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm");
       Scanner h = new Scanner(System.in);

       System.out.print("Enter date of birth[dd/mm/yyyy hh:mm]: ");
       String b = h.nextLine();

       LocalDateTime bd = LocalDateTime.parse(b,T);
       LocalDateTime cd = LocalDateTime.now();

       int hr = cd.getHour() - bd.getHour();
       int mn = cd.getMinute() - bd.getMinute();

       Period time = Period.between(bd.toLocalDate(),cd.toLocalDate());

       System.out.print("Age is: "+time.getYears()+ " years,"+time.getMonths()+ " months, " +time.getDays()+ " days, "+hr+ " hours, " +mn+ " minutes old");
    }
}

#1


84  

Unfortunately there doesn't seem to be a period class that spans time as well, so you might have to do the calculations on your own.

不幸的是,似乎没有一个周期类也跨越时间,所以你可能需要自己计算。

Forunately the date and time classes have a lot of utility methods that simplify that to some degree. Here's a way to calculate the difference although not necessarily the fastest:

通常,日期和时间类有很多实用的方法可以在一定程度上简化它。这里有一种计算差异的方法,虽然不一定是最快的:

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.");

//prints: 29 years 8 months 24 days 22 hours 54 minutes 50 seconds.

The basic idea is this: create a temporary start date and get the full years to the end. Then adjust that date by the number of years so that the start date is less then a year from the end. Repeat that for each time unit in descending order.

最基本的想法是:创建一个临时的开始日期,并将其持续到年底。然后根据年数调整这个日期,以便从年底开始的日期少于一年。按降序对每个时间单元重复上述操作。

Finally a disclaimer: I didn't take different timezones into account (both dates should be in the same timezone) and I also didn't test/check how daylight saving time or other changes in a calendar (like the timezone changes in Samoa) affect this calculation. So use with care.

最后一个声明:我没有考虑不同的时区(两个日期都应该在同一个时区),也没有测试/检查日光节约时间或日历中的其他更改(比如萨摩亚的时区更改)是如何影响这个计算的。所以请小心使用。

#2


280  

I found the best way to do this is with ChronoUnit.

我发现最好的方法是用ChronoUnit。

long minutes = ChronoUnit.MINUTES.between(fromDate, toDate);
long hours = ChronoUnit.HOURS.between(fromDate, toDate);

Additional documentation is here: https://docs.oracle.com/javase/tutorial/datetime/iso/period.html

其他文档如下:https://docs.oracle.com/javase/tutorial/datetime/iso/period.html

#3


12  

Here a single example using Duration and TimeUnit to get 'hh:mm:ss' format.

这里有一个例子,使用持续时间和时间单位来获得“hh:mm:ss”格式。

                Duration dur = Duration.between(LocalDateTimeIni, LocalDateTimeEnd);
                long millis = dur.toMillis();

                String.format("%02d:%02d:%02d", 
                        TimeUnit.MILLISECONDS.toHours(millis),
                        TimeUnit.MILLISECONDS.toMinutes(millis) - 
                        TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millis)),
                        TimeUnit.MILLISECONDS.toSeconds(millis) - 
                        TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis)));

#4


4  

And the version of @Thomas in Groovy with takes the desired units in a list instead of hardcoding the values. This implementation (which can easily ported to Java - I made the function declaration explicit) makes Thomas approach more reuseable.

Groovy中的@Thomas版本在列表中获取所需的单元,而不是硬编码值。这个实现(可以很容易地移植到Java -我使函数声明显式)使Thomas方法更可重用。

def fromDateTime = LocalDateTime.of(1968, 6, 14, 0, 13, 0)
def toDateTime = LocalDateTime.now()
def listOfUnits = [
    ChronoUnit.YEARS, ChronoUnit.MONTHS, ChronoUnit.DAYS,
    ChronoUnit.HOURS, ChronoUnit.MINUTES, ChronoUnit.SECONDS,
    ChronoUnit.MILLIS]

println calcDurationInTextualForm(listOfUnits, fromDateTime, toDateTime)    

String calcDurationInTextualForm(List<ChronoUnit> listOfUnits, LocalDateTime ts, LocalDateTime to)
{
    def result = []

    listOfUnits.each { chronoUnit ->
        long amount = ts.until(to, chronoUnit)
        ts = ts.plus(amount, chronoUnit)

        if (amount) {
            result << "$amount ${chronoUnit.toString()}"
        }
    }

    result.join(', ')
}

At the time of this writing,the code above returns 47 Years, 8 Months, 9 Days, 22 Hours, 52 Minutes, 7 Seconds, 140 Millis. And, for @Gennady Kolomoets input, the code returns 23 Hours.

在撰写本文时,上述代码将返回47年、8个月、9天、22小时、52分钟、7秒、140米。对于@Gennady Kolomoets输入,代码返回23小时。

When you provide a list of units it must be sorted by size of the units (biggest first):

当你提供一个单位列表时,它必须按单位的大小排序(最大的优先):

def listOfUnits = [ChronoUnit.WEEKS, ChronoUnit.DAYS, ChronoUnit.HOURS]
// returns 2495 Weeks, 3 Days, 8 Hours

#5


2  

There is some problem for Tapas Bose code and Thomas code. If time differenсe is negative, array gets the negative values. For example if

Tapas Bose代码和Thomas代码存在一些问题。如果时间differenсe是负的,数组的负值。例如,如果

LocalDateTime toDateTime = LocalDateTime.of(2014, 9, 10, 6, 46, 45);
LocalDateTime fromDateTime = LocalDateTime.of(2014, 9, 9, 7, 46, 45);

it returns 0 years 0 months 1 days -1 hours 0 minutes 0 seconds.

它返回0年0月1天-1小时0分钟0秒。

I think the right output is: 0 years 0 months 0 days 23 hours 0 minutes 0 seconds.

我认为正确的输出是:0年0月0天23小时0分钟0秒。

I propose to separate the LocalDateTime instances on LocalDate and LocalTime instances. After that we can obtain the Java 8 Period and Duration instances. The Duration instance is separated on the number of days and throughout-the-day time value (< 24h) with subsequent correction of the period value. When the second LocalTime value is before the firstLocalTime value, it is necessary to reduce the period for one day.

我建议在LocalDate和LocalTime实例上分离LocalDateTime实例。之后,我们可以获得Java 8周期和持续时间实例。持续时间的实例在天数和每天的时间值(< 24h)之间进行分离,并随后对周期值进行修正。当第二个LocalTime值在第一个LocalTime值之前,有必要减少一天的时间。

Here's my way to calculate the LocalDateTime difference:

下面是我计算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;
}

The above method can be used to calculate the difference of any local date and time values, for example:

上述方法可用于计算任何本地日期和时间值的差异,例如:

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;
}

It is convenient to write a unit test for the above method (both of them are PeriodDuration class members). Here's the code:

为上述方法编写单元测试非常方便(它们都是周期化类成员)。这是代码:

@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);
}

}

}

All tests are successful whether or not the value of the first LocalDateTime is before and for any LocalTime values.

无论第一个LocalDateTime的值是之前还是任何LocalTime值,所有测试都是成功的。

#6


0  

Here is a very simple answer to your question. It works.

这里有一个非常简单的答案来回答你的问题。它的工作原理。

import java.time.*;
import java.util.*;
import java.time.format.DateTimeFormatter;
public class MyClass {
    public static void main(String args[]) {
       DateTimeFormatter T = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm");
       Scanner h = new Scanner(System.in);

       System.out.print("Enter date of birth[dd/mm/yyyy hh:mm]: ");
       String b = h.nextLine();

       LocalDateTime bd = LocalDateTime.parse(b,T);
       LocalDateTime cd = LocalDateTime.now();

       int hr = cd.getHour() - bd.getHour();
       int mn = cd.getMinute() - bd.getMinute();

       Period time = Period.between(bd.toLocalDate(),cd.toLocalDate());

       System.out.print("Age is: "+time.getYears()+ " years,"+time.getMonths()+ " months, " +time.getDays()+ " days, "+hr+ " hours, " +mn+ " minutes old");
    }
}