Как лучше всего определить количество дней и месяцев между двумя java .time.Instant объектами? - PullRequest
0 голосов
/ 12 апреля 2020

ПРИМЕЧАНИЕ. Выполните поиск в Google, прежде чем отмечать этот вопрос как дубликат. Я искал и просматривал этот вопрос, и все ответы, которые я нашел, были либо для LocalDate, Joda, либо для устаревшего Java Date.

Мне потребовалось довольно много времени, чтобы исследовать этот вопрос, поэтому я ' Мы решили поделиться этим как ответом.

Я хотел бы рассчитать (приблизительное) количество месяцев и дней между двумя Java Инстансами (объектами java .time). Мгновенное)?

Ответы [ 2 ]

1 голос
/ 12 апреля 2020

Во-первых, то, что вы спрашиваете, не является четко определенным. Например, между моментами 2020-03-01T06: 00: 00Z и 2020-03-31T05: 00: 00Z могут быть:

  • 29 дней 23 часа в часовом поясе Австралии / Мельбурна;
  • 30 дней в часовом поясе Европы / Парижа;
  • 1 месяц 1 день в часовом поясе Америки / Лос-Анджелеса.

Точный результат в заданном часовом поясе

    ZoneId zone = ZoneId.of("America/Los_Angeles");
    Instant start = Instant.parse("2020-03-01T06:00:00Z");
    Instant end = Instant.parse("2020-03-31T05:00:00Z");
    ZonedDateTime startZdt = start.atZone(zone);
    LocalDate startDate = startZdt.toLocalDate();
    ZonedDateTime endZdt = end.atZone(zone);
    LocalDate endDate = endZdt.toLocalDate();
    Period p = Period.between(startDate, endDate);
    if (startZdt.plus(p).isAfter(endZdt)) {
        // The time of day on the end date is earlier, so don’t count a full date
        endDate = endDate.minusDays(1);
        p = Period.between(startDate, endDate);
    }
    System.out.println(p);

Вывод:

P1M1D

Считать как период 1 месяц 1 день.

Приблизительный результат независимо от часового пояса

Предпочитаю оставить как можно большую часть вычислений на java .time. Сюда входит оценка продолжительности месяца.

    Duration diff = Duration.between(start, end);
    Duration durationOfAMonth = ChronoUnit.MONTHS.getDuration();
    long months = diff.dividedBy(durationOfAMonth);
    diff = diff.minus(durationOfAMonth.multipliedBy(months));
    long days = diff.toDays();

    System.out.println("" + months + " months " + days + " days");

0 месяцев 29 дней

0 голосов
/ 12 апреля 2020

Я отказался от приблизительного решения (предполагается, что все месяцы имеют 30,44 дня). Я решил использовать что-то вроде этого:

Duration duration = Duration.between(instant1, instant2).abs(); /* if want negative values remove .abs() */
long hours = duration.toHours();
double daysAndMonthsInDays = hours / 24.0;
int months = daysAndMonthsInDays / 30.44; //average number of days per month
int days = daysAndMonthsInDays - months * 30.44;

Пожалуйста, опубликуйте другой ответ, если есть лучшее решение, использующее класс Duration или что-то еще. Я решил не конвертировать Instant в LocalDate и выполнить конвертацию на этом уровне. Это не будет использовать приблизительное значение 30,44 дня в месяце, а скорее фактическое число.

...