bread butter
bread butter

Reputation: 617

how to get a list of dates between two dates in java ? How to include/exclude start date/end date also?

I have tried the example given in stack overflow how to get a list of dates between two dates in java

The code works perfectly. But there is a small problem. I don't get the end date also in my List. How do I choose to include/exclude the start date and include the end date ? Do, I do that manually by using remove() and add() or can Joda API do that for me?

Upvotes: 2

Views: 7175

Answers (2)

Basil Bourque
Basil Bourque

Reputation: 338654

Using java.time

The Joda-Time project is now in maintenance mode, with the team advising migration to the java.time classes.

Half-open

Date-time work commonly uses the Half-Open approach to defining a span of time where the beginning is inclusive and the ending is exclusive. I believe consistent use of this approach in both your code and in your users’ business makes life much easier, avoiding amibiguities that can result in misunderstandings or errors.

The java.time classes use the Half-Open approach. Keep that in mind when using Period, Duration, and ChronUnit classes.

LocalDate start = LocalDate.of( 2017 , 1 , 23 );
LocalDate stop = LocalDate.of( 2017 , 2 , 14 );

List<LocalDate> dates = new ArrayList<>( (int) ChronoUnit.DAYS.between( start , stop ) ) ; 
LocalDate ld = start ;
while( ld.isBefore( stop ) ) {  // Half-open approach, ending is exclusive.
    dates.add( ld );
    // Set up the next loop.
    ld = ld.plusDays( 1 );
}

If you insist on that ending date to be inclusive, add a day to the input.

LocalDate stop = LocalDate.of( 2017 , 2 , 14 ).plusDays( 1 );  // Effectively making ending date inclusive.

…or (A) change the logic of the while test from isBefore to ! isAfter, and (B) add one to the initial capacity of the ArrayList.

List<LocalDate> dates = new ArrayList<>( ( (int) ChronoUnit.DAYS.between( start , stop ) ) + 1 ) ; // Add one to accommodate inclusive ending (*not* Half-Open).
LocalDate ld = start ;
while( ! ld.isAfter( stop ) ) {  // Ending is inclusive (*not* Half-Open). So using "not after" logic rather than "is before". 
    dates.add( ld );
    // Set up the next loop.
    ld = ld.plusDays( 1 );
}

Stream<LocalDate>

By the way, this code gets simpler in Java 9 where you can get a Stream<LocalDate from LocalDate::datesUntil method. That call returns a sequential ordered stream of dates.

A variant of that method lets you specify an amount to increment the dates. So, for example, instead of the default of single day increment, you can increment by two to get every-other-day.


About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

Where to obtain the java.time classes?

The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

Upvotes: 1

kosa
kosa

Reputation: 66637

Based on API, it seems there is no direct way to choose include.

One hack may be, just add +1 to number of days.

List<LocalDate> dates = new ArrayList<LocalDate>();
int days = Days.daysBetween(startDate, endDate).getDays()+1;
for (int i=0; i < days; i++) {
    LocalDate d = startDate.withFieldAdded(DurationFieldType.days(), i);
    dates.add(d);
}

Upvotes: 6

Related Questions