Обчисліть дні між двома датами на Java 8


251

Я знаю, що існує багато запитань щодо SO, як отримати, але я хочу та приклади, використовуючи нові Java 8 Date api. Я також знаю бібліотеку JodaTime, але хочу працювати без зовнішніх бібліотек.

Функція повинна скаржитися на такі обмеження:

  1. Запобігання помилкам із часу побачення
  2. Введення - це два об'єкти Date (без часу, я знаю localdatetime, але мені потрібно робити з екземплярами дати)

2
Щось подібне, наприклад ?
MadProgrammer

@MadProgrammer Не дуже - Тривалість не найкраще підходить для цього ...
assylias

@assylias Добре, ніж те, що було в ОП
MadProgrammer

@assylias Тоді що таке?
MadProgrammer

16
@MadProgrammer DAYS.between(localDate1, localDate2).
assylias

Відповіді:


435

Якщо ви хочете логічних днів календаря , використовуйте DAYS.between()метод із java.time.temporal.ChronoUnit:

LocalDate dateBefore;
LocalDate dateAfter;
long daysBetween = DAYS.between(dateBefore, dateAfter);

Якщо ви хочете буквально 24 години , ( тривалість ), ви можете використовувати Durationклас замість цього:

LocalDate today = LocalDate.now()
LocalDate yesterday = today.minusDays(1);
// Duration oneDay = Duration.between(today, yesterday); // throws an exception
Duration.between(today.atStartOfDay(), yesterday.atStartOfDay()).toDays() // another option

Для отримання додаткової інформації зверніться до цього документа .


15
Це кидає виняток, оскільки метод Duration.between вимагає тимчасових об'єктів, здатних підтримувати блок SECONDS . Натомість спробуйте Duration.between(today.atTime(0, 0), yesterday.atTime(0, 0)).toDays().
VGR

5
Замість today.atTime(0, 0)вас можна зробити today.atStartOfDay().
eee

5
@REACHUS Можливо, -1 було трохи суворим, оскільки запропонований вами код працює, але "Тривалість" призначена для вимірювання "часу, що базується на часі". Існує вбудований спосіб вимірювання кількості днів, який не потребує перетворення з дати в дату.
assylias

Краща відповідь для LocalDate - відповідь @Sunil B нижче:ChronoUnit.DAYS.between(firstDate, secondDate)
Lappro

@Lappro, чому це краще? Він використовує той самий метод, що і моя відповідь
синтагма

130

На основі коментарів VGR ось що ви можете використовувати:

ChronoUnit.DAYS.between(firstDate, secondDate)

38

Ви можете використовувати until():

LocalDate independenceDay = LocalDate.of(2014, Month.JULY, 4);
LocalDate christmas = LocalDate.of(2014, Month.DECEMBER, 25);

System.out.println("Until christmas: " + independenceDay.until(christmas));
System.out.println("Until christmas (with crono): " + independenceDay.until(christmas, ChronoUnit.DAYS));

4
Щойно я стикався з першою версією, untilце те, що він повертає об'єкт Period . Це поверне число років / місяців / днів між двома датами, а не фактичну кількість днів. І getDays () на Період повертає лише частину днів (без урахування кількості років чи місяців), а не загальну кількість днів. Друга версія працює саме так, як потрібно, щоб отримати кількість днів між двома датами.
М. Джастін

Чи є для цього повна альтернатива? Оскільки йому потрібен Android SDk 26 і вище
ralphgabb

12

Ви можете використовувати DAYS.betweenзjava.time.temporal.ChronoUnit

напр

import java.time.temporal.ChronoUnit;

public long getDaysCountBetweenDates(LocalDate dateBefore, LocalDate dateAfter) {
    return DAYS.between(dateBefore, dateAfter);
}

10

Якщо startDate і endDate є примірником java.util.Date

Ми можемо використовувати метод між () з перерахунку ChronoUnit :

public long between(Temporal temporal1Inclusive, Temporal temporal2Exclusive) {
    //..
}

ChronoUnit.DAYS відлічує дні, які закінчили 24 години .

import java.time.temporal.ChronoUnit;

ChronoUnit.DAYS.between(startDate.toInstant(), endDate.toInstant());

//OR 

ChronoUnit.DAYS.between(Instant.ofEpochMilli(startDate.getTime()), Instant.ofEpochMilli(endDate.getTime()));

8

Використовуйте DAYS в enum java.time.temporal.ChronoUnit . Нижче наведено Приклад коду:

Вихід: * Кількість днів між початковою датою: 2015-03-01 та датою закінчення: 2016-03-03 є ==> 368. ** Кількість днів між початковою датою: 2016-03-03 та датою закінчення: 01.03.2015 є ==> -368 *

package com.bitiknow.date;

import java.time.LocalDate;
import java.time.temporal.ChronoUnit;

/**
 * 
 * @author pradeep
 *
 */
public class LocalDateTimeTry {
    public static void main(String[] args) {

        // Date in String format.
        String dateString = "2015-03-01";

        // Converting date to Java8 Local date
        LocalDate startDate = LocalDate.parse(dateString);
        LocalDate endtDate = LocalDate.now();
        // Range = End date - Start date
        Long range = ChronoUnit.DAYS.between(startDate, endtDate);
        System.out.println("Number of days between the start date : " + dateString + " and end date : " + endtDate
                + " is  ==> " + range);

        range = ChronoUnit.DAYS.between(endtDate, startDate);
        System.out.println("Number of days between the start date : " + endtDate + " and end date : " + dateString
                + " is  ==> " + range);

    }

}

8

Усі говорять про використання ChronoUnit.DAYS.між ними, але це просто делегування іншого методу, яким ви могли б зателефонувати собі. Так ви могли і зробити firstDate.until(secondDate, ChronoUnit.DAYS).

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


FWIW ... Я не впевнений, чому обидва існують. Чи бувають випадки, коли один є більш читабельним, і коли є інший? Коли / чому?
нафг

5

Ось вам:

public class DemoDate {
    public static void main(String[] args) {
        LocalDate today = LocalDate.now();
        System.out.println("Current date: " + today);

        //add 1 month to the current date
        LocalDate date2 = today.plus(1, ChronoUnit.MONTHS);
        System.out.println("Next month: " + date2);

        // Put latest date 1st and old date 2nd in 'between' method to get -ve date difference
        long daysNegative = ChronoUnit.DAYS.between(date2, today);
        System.out.println("Days : "+daysNegative);

        // Put old date 1st and new date 2nd in 'between' method to get +ve date difference
        long datePositive = ChronoUnit.DAYS.between(today, date2);
        System.out.println("Days : "+datePositive);
    }
}

5

Отримайте кількість днів до Різдва від поточного дня, спробуйте це

System.out.println(ChronoUnit.DAYS.between(LocalDate.now(),LocalDate.of(Year.now().getValue(), Month.DECEMBER, 25)));

3

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

public long daysInBetween(java.time.LocalDate startDate, java.time.LocalDate endDate) {
  // Check for null values here

  return endDate.toEpochDay() - startDate.toEpochDay();
}

1
Ви потрапляєте у пастку, щоб використовувати "Period.bet between (date1, date2) .getDays ()", не розуміючи, що ви втрачаєте різницю за місяці та роки.
MrSmith42

2

отримати дні між двома датами, наприклад, java.util.Date

public static long daysBetweenTwoDates(Date dateFrom, Date dateTo) {
            return DAYS.between(Instant.ofEpochMilli(dateFrom.getTime()), Instant.ofEpochMilli(dateTo.getTime()));
        }

1

Я знаю, що це питання стосується Java 8, але з Java 9 ви можете використовувати:

public static List<LocalDate> getDatesBetween(LocalDate startDate, LocalDate endDate) {
    return startDate.datesUntil(endDate)
      .collect(Collectors.toList());
}

0

Використовуйте клас або метод, який найкраще відповідає вашим потребам:

  • тривалість класу,
  • ПеріодКлас ,
  • або методом ChronoUnit . between between .

A Тривалість вимірює кількість часу, використовуючи значення на основі часу (секунди, наносекунди).

Період використовує значення на основі дати (роки, місяці, дні).

Метод ChronoUnit.between корисний, коли потрібно виміряти кількість часу лише за одну одиницю часу, наприклад дні чи секунди.

https://docs.oracle.com/javase/tutorial/datetime/iso/period.html

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.