Java 8: Різниця між двома LocalDateTime в декількох одиницях


266

Я намагаюся обчислити різницю між двома LocalDateTime.

Вихід повинен бути форматом y years m months d days h hours m minutes s seconds. Ось що я написав:

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

Вихід, який я отримую, - це 29 years 8 months 24 days 12 hours 0 minutes 50 seconds. Я перевірив свій результат на цьому веб-сайті (зі значеннями 12/16/1984 07:45:55та 09/09/2014 19:46:45). На наступному скріншоті показано вихід:

Конвертор епох

Я майже впевнений, що поля після значення місяця неправильно входять у мій код. Будь-яка пропозиція буде дуже корисною.

Оновлення

Я перевірив свій результат на іншому веб-сайті, і результат, який я отримав, відрізняється. Ось це: Обчисліть тривалість між двома датами (результат: 29 років, 8 місяців, 24 дні, 12 годин, 0 хвилин і 50 секунд).

Оновлення

Оскільки я отримав два різних результати з двох різних сайтів, мені цікаво, чи законний алгоритм мого розрахунку чи ні. Якщо я використовую наступні два LocalDateTimeоб'єкти:

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

Тоді вихід виходить: 29 years 8 months 25 days -1 hours -5 minutes -10 seconds.

З цього посилання має бути 29 years 8 months 24 days 22 hours, 54 minutes and 50 seconds. Тож алгоритм теж повинен поводитися з від’ємними числами.

Зауважте, питання полягає не в тому, який сайт дав мені результат, мені потрібно знати правильний алгоритм і потрібно мати правильні результати.


Просто здогадка, але може Period.between()застосувати деяке округлення?
Томас

3
Я просто ще раз переглянув код і, здається, веб-сайт невірний (Спробуйте розрахувати самостійно). Якщо ви пропустите дату, тобто різниці в році, місяці та дні, ви отримаєте час початку 7:45:55та час закінчення 19:46:45(або 7:46:45ПМ). Отже різниця між цими двома разів становить 12 годин, 0 хвилин і 50 секунд, а ніколи 23 години, 34 хвилини і 12 секунд. Тож ваш фактичний розрахунок здається правильним, принаймні на часовій частині.
Томас

1
Цікаве явище на цьому веб-сайті: додайте 10 років до дати початку, а різниця в годинах змінюється від 23 до 8 - безумовно, ознака помилок.
Томас

8
Зауважте, що оскільки LocalDateTimeнемає часового поясу, то може бути і не було однозначної відповіді. Навіть якщо ви припускаєте, що початковий і кінцевий часові зони однакові, у деяких зонах дати, наприклад, 09.09.2014, будуть в літній та літній час, а в інших - не. Це може скинути речі за годину. Тож обчислювати різницю до другого безглуздо, якщо це не вирішено.
Stuart Marks

2
Чи розумієте ви, що використання LocalDateTimeрезультатів дає нереалістичні результати, оскільки цьому класу навмисно не вистачає жодної концепції часового поясу чи зміщення від UTC? Для реалістичних значень призначте часовий пояс через ZoneIdдля використання ZonedDateTime.
Василь Бурк

Відповіді:


163

На жаль, не здається, що існує період періоду, який також охоплює час, тому, можливо, доведеться робити розрахунки самостійно.

На щастя, у класах дати та часу є безліч корисних методів, які певною мірою спрощують це. Ось спосіб обчислити різницю, хоча не обов'язково найшвидший:

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.

Основна ідея така: створити тимчасову дату початку і довести цілі роки до кінця. Потім відкоригуйте дату на кількість років, щоб дата початку була меншою за рік від кінця. Повторіть це для кожної одиниці часу у порядку зменшення.

Нарешті, відмова від відповідальності : я не враховував різні часові пояси (обидві дати повинні бути в одному часовому поясі), а також не перевіряв / перевіряв, як літній час або інші зміни в календарі (наприклад, зміни часового поясу в Самоа) впливають на цей розрахунок. Тому використовуйте обережно.


1
Ви маєте ту саму основну ідею, тому мій підсумок, але будь ласка, спробуйте використати один і той же вхід, інакше різний результат буде заплутаним.
Meno Hochschild

@MenoHochschild він є той же входом, просто взятий з оновлень , де OP має проблеми з негативним разом. ;)
Томас

1
Хороший алгоритм, але неправильний тип (див. Відмову від Томаса). Перш ніж робити розрахунок, слід перетворити змінні LocalDateTime в ZonedDateTime, використовуючи, наприклад, часовий пояс за замовчуванням (або будь-який потрібний вам часовий пояс): ZonedDateTime fromZonedDateTime = fromDateTime.atZone (ZoneId.systemDefault ());
Трістан

2
@Thomas У вашому прикладі використовується також Java 8 - і питання позначено як java-8. Насправді ваш приклад навіть використовується ChronoUnit:), але виконайте роботу "вручну".
Євген Бересовський

3
@EugeneBeresovsky о так, ти маєш рацію. Повністю пропустив це;) - Крім того, ви все одно доведеться віднімати великі блоки з інтервалу , так як, наприклад , long minutes = ChronoUnit.MINUTES.between(fromDate, toDate);буде повертати число більше 59 для будь-якого інтервалу , по крайней мере , 1 годину - і це не те , що ОП хоче. Враховуючи це, ви не зможете здійснити 6 дзвінків ChronoUnit#between()і робити.
Томас

503

Я знайшов найкращий спосіб зробити це за допомогою ChronoUnit.

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

Додаткова документація тут: https://docs.oracle.com/javase/tutorial/datetime/iso/period.html


8
Я не бачу справжнього покращення. За порівнянні з відповіддю акцептував Томаса ви просто замінити tempDateTime.until( toDateTime, ChronoUnit.YEARS)з ChronoUnit.YEARS.between(fromDate, toDate). Але важливі додаткові рядки, як-от tempDateTime.plusYears( years )тощо, повністю відсутні у вашій відповіді, тому це не допомагає ОП. Повний алгоритм має значення!
Мено Хоксшильд

9
Мені це подобається краще, оскільки воно є більш лаконічним і читабельніше. Це найкращий спосіб знайти різницю між двома датами.
Сомая Кумбера

7
@SomaiahKumbera Ні, ви повністю не пропустите критичну точку. ОП не хоче тривалості лише в одній одиниці, а в декількох одиницях , і тому ця відповідь взагалі не є реальною відповіддю. Занепокоєння ОП просто не вирішується. Будь ласка, будь ласка, прочитайте питання ще раз. (Здається, що багато учасників опитування неправильно зрозуміли це питання).
Мено Хоксшильд

125
@ MenoHochschild, я думаю, що ти насправді не вистачає критичної точки. ОП отримали свою відповідь більше року тому. 36 тисяч людей, які переглядають це питання, не переймаються конкретним питанням ОП. Вони привели сюди Google, і моя відповідь дала їм те, що вони шукали - чисте і просте рішення для отримання різниці між двома датами.
сатнам

10
Мені знадобилася секунда різниці між двома датами і почала впроваджувати власне рішення. Незабаром це здається складним, і я взяв на себе google. відповідь satnam може не відповісти на питання ОП, але, безумовно, мені дуже допомогло, і я ставлю на облік багато інших, як я.
Юліан

43

Ось єдиний приклад, використовуючи Duration та TimeUnit, щоб отримати формат '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)));

2
Це на самому ділі можна зробити це в такий спосіб : String.format("%02d:%02d:%02d",dur.toHoursPart(), dur.toMinutesPart(), dur.toSecondsPart());. Методи частини дають вам правильні числа для побудови рядка. Я думаю, що це "читабельніше".
Даанті

Бічна примітка до мого попереднього коментаря: методи деталей доступні лише у JDK 9 та новіших версій.
Даанті

40

Це повинно бути простіше!

Duration.between(startLocalDateTime, endLocalDateTime).toMillis();

1
Я вважаю, що це насправді семантично правильне рішення, починаючи з Java 8. А до цієї версії JodaTime робить те саме.
Vrakfall

9

TL; DR

Duration duration = Duration.between(start, end);
duration = duration.minusDays(duration.toDaysPart()); // essentially "duration (mod 1 day)"
Period period = Period.between(start.toLocalDate(), end.toLocalDate());

а потім використовувати методи period.getYears(), period.getMonths(), period.getDays(), duration.toHoursPart(), duration.toMinutesPart(), duration.toSecondsPart().


Розгорнута відповідь

Я відповім на початкове запитання, тобто як отримати різницю у часі між двома LocalDateTimesроками, місяцями, днями, годинами і хвилинами, щоб "сума" (див. Примітку нижче) всіх значень для різних одиниць дорівнювала загальній часова різниця та така, що значення в кожній одиниці менше, ніж у наступної більшої одиниці, тобто minutes < 60, hours < 24тощо.

Дано два LocalDateTimes start і end, напр

LocalDateTime start = LocalDateTime.of(2019, 11, 29, 17, 15);
LocalDateTime end = LocalDateTime.of(2020, 11, 30, 18, 44);

ми можемо представити абсолютний проміжок часу між ними за допомогою Duration—можливо, використовуючи Duration.between(start, end). Але найбільшою одиницею, яку ми можемо витягти, Durationє дні (як часова одиниця, еквівалентна 24 год) - див. Примітку нижче для пояснення. Для використання більших одиниць (місяців, років) ми можемо представити це Durationпарою (Period , Duration), де Periodвимірюється різниця до точності днів, а Durationпоказник решта:

Duration duration = Duration.between(start, end);
duration = duration.minusDays(duration.toDaysPart()); // essentially "duration (mod 1 day)"
Period period = Period.between(start.toLocalDate(), end.toLocalDate());

Тепер ми можемо просто використовувати методи, визначені на PeriodтаDuration витягувати окремі одиниці:

System.out.printf("%d years, %d months, %d days, %d hours, %d minutes, %d seconds",
        period.getYears(), period.getMonths(), period.getDays(), duration.toHoursPart(),
        duration.toMinutesPart(), duration.toSecondsPart());
1 years, 0 months, 1 days, 1 hours, 29 minutes, 0 seconds

або, використовуючи стандартний формат:

System.out.println(period + " + " + duration);
P1Y1D + PT1H29M

Зверніть увагу на роки, місяці та дні

Зауважте, що, за java.timeзадумом "," одиниці ", такі як" місяць "або" рік ", не представляють собою фіксованого, абсолютного часового значення - вони залежать від дати та календаря, як показано в наступному прикладі:

LocalDateTime
        start1 = LocalDateTime.of(2020, 1, 1, 0, 0),
        end1 = LocalDateTime.of(2021, 1, 1, 0, 0),
        start2 = LocalDateTime.of(2021, 1, 1, 0, 0),
        end2 = LocalDateTime.of(2022, 1, 1, 0, 0);
System.out.println(Period.between(start1.toLocalDate(), end1.toLocalDate()));
System.out.println(Duration.between(start1, end1).toDays());
System.out.println(Period.between(start2.toLocalDate(), end2.toLocalDate()));
System.out.println(Duration.between(start2, end2).toDays());
P1Y
366
P1Y
365

5

Існує певна проблема з кодом Tapas Bose і кодом Томаса. Якщо відмінність часу від’ємна, масив отримує від’ємні значення. Наприклад, якщо

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 секунд.

Я пропоную відокремити екземпляри LocalDateTime від екземплярів LocalDate та LocalTime. Після цього ми можемо отримати екземпляри Java 8 періоду та тривалості. Екземпляр "Тривалість" відокремлюється від кількості днів та цілоденного значення часу (<24 год) з подальшим виправленням значення періоду. Коли друге значення 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.


Я не можу відтворити ваше твердження про те, що Томас, використовуючи вказаний вище код, створює змішані знаки. Мій результат: "0 років 0 місяців 0 днів 23 години 0 хвилин 0 секунд". І я протестував саме зараз.
Мено Хохшильд

Дякую за коментар Я ретельно перевірив код Томаса, дійсно, він працює правильно! Магія виконується LocalDateTime, поки метод виправлення одиниць хроно. Негативні значення в коді Томаса з’являються, якщо перший DateTime пізніше другого. Але це можна легко виправити, наприклад, як я це робив у наведеному вище коді. Знову дякую.
Геннадій Коломоєць

Ну, код Томаса і моя бібліотека Time4J, використовуючи той самий алгоритм для обчислення тривалості, можуть давати негативні ознаки, але тільки на всю тривалість. Це найважливіший момент! Знак стосується всієї тривалості і, отже, описує, якщо початок пізніше кінця і ніколи не пов'язаний з компонентами однієї тривалості. Змішані знаки тут неможливі і перешкоджали б такій інтерпретації початку відносно кінця (зустрічним прикладом є Joda-Time-period або java.time.Periodколи користувачі можуть застосовувати / виробляти такі змішані знаки через різну внутрішню конструкцію).
Мено Хоксшильд

5

І версія @Thomas в Groovy з приймає потрібні одиниці у списку замість жорсткого кодування значень. Така реалізація (яка легко переноситься на Java - я зробив декларацію функції явною) робить Томаса підхід більш корисним для повторного використання.

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(', ')
}

На момент написання цього тексту повертається вищевказаний код 47 Years, 8 Months, 9 Days, 22 Hours, 52 Minutes, 7 Seconds, 140 Millis. А для введення @Gennady Kolomoets код повертається 23 Hours.

Коли ви надаєте список одиниць, він повинен бути відсортований за розміром одиниць (найбільше перше):

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

4

Ось дуже проста відповідь на ваше запитання. Це працює.

import java.time.*;
import java.util.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;

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();

    long minutes = ChronoUnit.MINUTES.between(bd, cd);
    long hours = ChronoUnit.HOURS.between(bd, cd);

    System.out.print("Age is: "+hours+ " hours, or " +minutes+ " minutes old");
}
}

1
Слід зазначити, що це не точно. спробуйте з цим. це говорить різницю в 1 хвилину. LocalDateTime bd = LocalDateTime.of (2019, 11, 26, 15, 03, 55); LocalDateTime cd = LocalDateTime.of (2019, 11, 26, 15, 04, 45);
Марк Amabile

Я ввійшов в минулу ніч і отримав Age is: 0 years,0 months, 1 days, -10 hours, -48 minutes old. Я не думаю, що це те, що було бажано.
Оле ВВ

@ OleV.V. Виправлено цю проблему
SavedBeau

1

Joda-Time

Оскільки для багатьох відповідей потрібна підтримка API 26, а мін API - 23, я вирішив це за кодом нижче:

import org.joda.time.Days

LocalDate startDate = Something
LocalDate endDate = Something
// The difference would be exclusive of both dates, 
// so in most of use cases we may need to increment it by 1
Days.daysBetween(startDate, endDate).days

1
Проект Joda-Time знаходиться в режимі обслуговування, його творець Стівен Колбурн продовжив створювати класи java.time, визначені в JSR 310. Більшість функцій java.time повертається назад до Java 6 та 7 в ThreeTen- Бекспортний проект. Далі адаптовано для раннього Android у проекті ThreeTenABP .
Василь Бурк

1

Після більш ніж п’яти років я відповідаю на моє запитання. Я думаю, що проблему з негативною тривалістю можна вирішити простою корекцією:

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

Period period = Period.between(fromDateTime.toLocalDate(), toDateTime.toLocalDate());
Duration duration = Duration.between(fromDateTime.toLocalTime(), toDateTime.toLocalTime());

if (duration.isNegative()) {
    period = period.minusDays(1);
    duration = duration.plusDays(1);
}
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);
long time[] = {hours, minutes, secs};
System.out.println(period.getYears() + " years "
            + period.getMonths() + " months "
            + period.getDays() + " days "
            + time[0] + " hours "
            + time[1] + " minutes "
            + time[2] + " seconds.");

Примітка: Сайт https://www.epochconverter.com/date-difference тепер правильно обчислює різницю в часі.

Дякую всім за вашу дискусію та пропозиції.


Дякую за відповідь. Для годин і менших ви можете скористатися і методами toHours, toMinutesі toSecondsметодами Duration. Оскільки Java 9 ще більше з toMinutesPart()і toSecondsPart(). І я не бачу сенсу загортати години, хвилини і секунди в масив, щоб знову їх вивезти. Взагалі гарна відповідь, хоча.
Оле В. В.

Після більш ніж п’яти років я відповідаю на моє запитання. Питання було розміщено з облікового запису з іншим ім’ям, назвою та місцеположенням. Не те, щоб це мало якесь значення, просто цікаво.
Оле В. В.

"Після більш ніж п'яти років я відповідаю на моє запитання" Я вважаю, що я був ОП :)
Тапас Босе
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.