How to iterate through range of Dates in Java?

JavaDateIteration

Java Problem Overview


In my script I need to perform a set of actions through range of dates, given a start and end date.
Please provide me guidance to achieve this using Java.

for ( currentDate = starDate; currentDate < endDate; currentDate++) {

}

I know the above code is simply impossible, but I do it in order to show you what I'd like to achieve.

Java Solutions


Solution 1 - Java

Well, you could do something like this using Java 8's time-API, for this problem specifically java.time.LocalDate (or the equivalent Joda Time classes for Java 7 and older)

for (LocalDate date = startDate; date.isBefore(endDate); date = date.plusDays(1))
{
    ...
}

I would thoroughly recommend using java.time (or Joda Time) over the built-in Date/Calendar classes.

Solution 2 - Java

JodaTime is nice, however, for the sake of completeness and/or if you prefer API-provided facilities, here are the standard API approaches.

When starting off with java.util.Date instances like below:

SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
Date startDate = formatter.parse("2010-12-20");
Date endDate = formatter.parse("2010-12-26");

Here's the legacy java.util.Calendar approach in case you aren't on Java8 yet:

Calendar start = Calendar.getInstance();
start.setTime(startDate);
Calendar end = Calendar.getInstance();
end.setTime(endDate);

for (Date date = start.getTime(); start.before(end); start.add(Calendar.DATE, 1), date = start.getTime()) {
    // Do your job here with `date`.
    System.out.println(date);
}

And here's Java8's java.time.LocalDate approach, basically exactly the JodaTime approach:

LocalDate start = startDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
LocalDate end = endDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();

for (LocalDate date = start; date.isBefore(end); date = date.plusDays(1)) {
    // Do your job here with `date`.
    System.out.println(date);
}

If you'd like to iterate inclusive the end date, then use !start.after(end) and !date.isAfter(end) respectively.

Solution 3 - Java

Java 8 style, using the java.time classes:

// Monday, February 29 is a leap day in 2016 (otherwise, February only has 28 days)
LocalDate start = LocalDate.parse("2016-02-28"),
          end   = LocalDate.parse("2016-03-02");

// 4 days between (end is inclusive in this example)
Stream.iterate(start, date -> date.plusDays(1))
        .limit(ChronoUnit.DAYS.between(start, end) + 1)
        .forEach(System.out::println);

Output:

2016-02-28
2016-02-29
2016-03-01
2016-03-02

Alternative:

LocalDate next = start.minusDays(1);
while ((next = next.plusDays(1)).isBefore(end.plusDays(1))) {
    System.out.println(next);
}

Java 9 added the datesUntil() method:

start.datesUntil(end.plusDays(1)).forEach(System.out::println);

Solution 4 - Java

This is essentially the same answer BalusC gave, but a bit more readable with a while loop in place of a for loop:

Calendar start = Calendar.getInstance();
start.setTime(startDate);
		
Calendar end = Calendar.getInstance();
end.setTime(endDate);

while( !start.after(end)){
    Date targetDay = start.getTime();
    // Do Work Here

    start.add(Calendar.DATE, 1);
}

Solution 5 - Java

Apache Commons

    for (Date dateIter = fromDate; !dateIter.after(toDate); dateIter = DateUtils.addDays(dateIter, 1)) {
        // ...
    }

Solution 6 - Java

private static void iterateBetweenDates(Date startDate, Date endDate) {
    Calendar startCalender = Calendar.getInstance();
	startCalender.setTime(startDate);
	Calendar endCalendar = Calendar.getInstance();
	endCalendar.setTime(endDate);

	for(; startCalender.compareTo(endCalendar)<=0;
          startCalender.add(Calendar.DATE, 1)) {
	    // write your main logic here
	}
		
}

Solution 7 - Java

We can migrate the logic to various methods foe Java 7, Java 8 and Java 9:

public static List<Date> getDatesRangeJava7(Date startDate, Date endDate) {
    List<Date> datesInRange = new ArrayList<>();
    Calendar startCalendar = new GregorianCalendar();
    startCalendar.setTime(startDate);
    Calendar endCalendar = new GregorianCalendar();
    endCalendar.setTime(endDate);
    while (startCalendar.before(endCalendar)) {
        Date result = startCalendar.getTime();
        datesInRange.add(result);
        startCalendar.add(Calendar.DATE, 1);
    }
    return datesInRange;
}

public static List<LocalDate> getDatesRangeJava8(LocalDate startDate, LocalDate endDate) {
    int numOfDays = (int) ChronoUnit.DAYS.between(startDate, endDate);
    return IntStream.range(0, numOfDays)
            .mapToObj(startDate::plusDays)
            .collect(Collectors.toList());
}

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

Then we can invoke these methods as:

SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
Date startDate = formatter.parse("2010-12-20");
Date endDate = formatter.parse("2010-12-26");
List<Date> dateRangeList = getDatesRangeJava7(startDate, endDate);
System.out.println(dateRangeList);

LocalDate startLocalDate = startDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
LocalDate endLocalDate = endDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
List<LocalDate> dateRangeList8 = getDatesRangeJava8(startLocalDate, endLocalDate);
System.out.println(dateRangeList8);
List<LocalDate> dateRangeList9 = getDatesRangeJava8(startLocalDate, endLocalDate);
System.out.println(dateRangeList9);

The output would be:

> [Mon Dec 20 00:00:00 IST 2010, Tue Dec 21 00:00:00 IST 2010, Wed Dec > 22 00:00:00 IST 2010, Thu Dec 23 00:00:00 IST 2010, Fri Dec 24 > 00:00:00 IST 2010, Sat Dec 25 00:00:00 IST 2010] > > [2010-12-20, 2010-12-21, 2010-12-22, 2010-12-23, 2010-12-24, > 2010-12-25] > > [2010-12-20, 2010-12-21, 2010-12-22, 2010-12-23, 2010-12-24, > 2010-12-25]

Solution 8 - Java

It’s built in: LocalDate.datesUntil() since Java 9

It seems that the answers until now have only been considering Java 8 and earlier. The Java 9+ way is:

	LocalDate startDate = LocalDate.of(2021, Month.JUNE, 29);
	LocalDate endDate = LocalDate.of(2021, Month.JULY, 3);
	
	startDate.datesUntil(endDate).forEach(System.out::println);

Output from this example is:

> 2021-06-29 > 2021-06-30 > 2021-07-01 > 2021-07-02

While the start date is inclusive, the end date is exclusive, as in your question the way I read it. If someone wants the end date to be included, it’s easy, just add a day to it:

	startDate.datesUntil(endDate.plusDays(1)).forEach(System.out::println);

> 2021-06-29 > 2021-06-30 > 2021-07-01 > 2021-07-02 > 2021-07-03

You can obviously iterate several years in this way, just as you can put a lengthier lambda where I just put the method reference System.out::println for demonstration.

Solution 9 - Java

public static final void generateRange(final Date dateFrom, final Date dateTo)
{
	final Calendar current = Calendar.getInstance();
	current.setTime(dateFrom);

	while (!current.getTime().after(dateTo))
	{
		// TODO

		current.add(Calendar.DATE, 1);
	}
}

Solution 10 - Java

Here is Java 8 code. I think this code will solve your problem.Happy Coding

    LocalDate start = LocalDate.now();
	LocalDate end = LocalDate.of(2016, 9, 1);//JAVA 9 release date
    Long duration = start.until(end, ChronoUnit.DAYS);
	System.out.println(duration);
	 // Do Any stuff Here there after
    IntStream.iterate(0, i -> i + 1)
             .limit(duration)
             .forEach((i) -> {});
     //old way of iteration
    for (int i = 0; i < duration; i++)
	 System.out.print("" + i);// Do Any stuff Here

Solution 11 - Java

Why not use epoch and loop through easily.

long startDateEpoch = new java.text.SimpleDateFormat("dd/MM/yyyy").parse(startDate).getTime() / 1000;
	
	long endDateEpoch = new java.text.SimpleDateFormat("dd/MM/yyyy").parse(endDate).getTime() / 1000;
	
	
	long i;
	for(i=startDateEpoch ; i<=endDateEpoch; i+=86400){
		
		System.out.println(i);
		
	}

Solution 12 - Java

You can write a class like it(implementing iterator interface) and iterate over it .

public class DateIterator implements Iterator<Date>, Iterable<Date>
{

 private Calendar end = Calendar.getInstance();
 private Calendar current = Calendar.getInstance();

 public DateIterator(Date start, Date end)
 {
     this.end.setTime(end);
     this.end.add(Calendar.DATE, -1);
     this.current.setTime(start);
     this.current.add(Calendar.DATE, -1);
 }

 @Override
 public boolean hasNext()
 {
     return !current.after(end);
 }

 @Override
 public Date next()
 {
     current.add(Calendar.DATE, 1);
     return current.getTime();
 }

 @Override
 public void remove()
 {
     throw new UnsupportedOperationException(
        "Cannot remove");
 }

 @Override
 public Iterator<Date> iterator()
 {
     return this;
 }
}

and use it like :

Iterator<Date> dateIterator = new DateIterator(startDate, endDate);
while(dateIterator.hasNext()){
	  Date selectedDate = dateIterator .next();

}

Solution 13 - Java

You can try this:

OffsetDateTime currentDateTime = OffsetDateTime.now();
for (OffsetDateTime date = currentDateTime; date.isAfter(currentDateTime.minusYears(YEARS)); date = date.minusWeeks(1))
{
	...
}

Solution 14 - Java

This will help you start 30 days back and loop through until today's date. you can easily change range of dates and direction.

private void iterateThroughDates() throws Exception {
    Calendar start = Calendar.getInstance();
    start.add(Calendar.DATE, -30);
    Calendar end = Calendar.getInstance();
    for (Calendar date = start; date.before(end); date.add(Calendar.DATE, 1))
        {
        System.out.println(date.getTime());
        }
}

Solution 15 - Java

The following snippet (uses java.time.format of Java 8) maybe used to iterate over a date range :

    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
    // Any chosen date format maybe taken  
	LocalDate startDate = LocalDate.parse(startDateString,formatter);
	LocalDate endDate = LocalDate.parse(endDateString,formatter);
	if(endDate.isBefore(startDate))
	{
		//error
	}
	LocalDate itr = null;
	for (itr = startDate; itr.isBefore(endDate)||itr.isEqual(itr); itr = itr.plusDays(1))
	{
		//Processing  goes here
	}

The plusMonths()/plusYears() maybe chosen for time unit increment. Increment by a single day is being done in above illustration.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser531743View Question on Stackoverflow
Solution 1 - JavaJon SkeetView Answer on Stackoverflow
Solution 2 - JavaBalusCView Answer on Stackoverflow
Solution 3 - JavaMartin AnderssonView Answer on Stackoverflow
Solution 4 - JavaChris M.View Answer on Stackoverflow
Solution 5 - JavaMikeView Answer on Stackoverflow
Solution 6 - Javakushal agrawalView Answer on Stackoverflow
Solution 7 - Javaakhil_mittalView Answer on Stackoverflow
Solution 8 - JavaOle V.V.View Answer on Stackoverflow
Solution 9 - Javakayz1View Answer on Stackoverflow
Solution 10 - Javajatin GoyalView Answer on Stackoverflow
Solution 11 - Javamridul4cView Answer on Stackoverflow
Solution 12 - JavajdevView Answer on Stackoverflow
Solution 13 - JavaPankaj SinghView Answer on Stackoverflow
Solution 14 - JavaJanuka samaranyakeView Answer on Stackoverflow
Solution 15 - JavaDevanshu KashyapView Answer on Stackoverflow