4

I attempted to generate the date range between date x and date y but failed. I have the same method in c# so I tried to modify it as much as I can but failed to get result. Any idea what I could fix?

private ArrayList<Date> GetDateRange(Date start, Date end) {
    if(start.before(end)) {
        return null;
    }

    int MILLIS_IN_DAY = 1000 * 60 * 60 * 24;
    ArrayList<Date> listTemp = new ArrayList<Date>();
    Date tmpDate = start;

    do {
        listTemp.add(tmpDate);
        tmpDate = tmpDate.getTime() + MILLIS_IN_DAY;
    } while (tmpDate.before(end) || tmpDate.equals(end));

    return listTemp;
}

To be honest I was trying to get all the dates starting from january 1st till the end of year 2012 that is december 31st. If any better way available, please let me know. Thanks

George Brighton
  • 5,131
  • 9
  • 27
  • 36
sys_debug
  • 3,883
  • 17
  • 67
  • 98

5 Answers5

16

Joda-Time

Calendar and Date APIs in java are really weird... I strongly suggest to consider jodatime, which is the de-facto library to handle dates. It is really powerful, as you can see from the quickstart: http://joda-time.sourceforge.net/quickstart.html.

This code solves the problem by using Joda-Time:

import java.util.ArrayList;
import java.util.List;

import org.joda.time.DateTime;


public class DateQuestion {

    public static List<DateTime> getDateRange(DateTime start, DateTime end) {

        List<DateTime> ret = new ArrayList<DateTime>();
        DateTime tmp = start;
        while(tmp.isBefore(end) || tmp.equals(end)) {
            ret.add(tmp);
            tmp = tmp.plusDays(1);
        }
        return ret;
    }

    public static void main(String[] args) {

        DateTime start = DateTime.parse("2012-1-1");
        System.out.println("Start: " + start);

        DateTime end = DateTime.parse("2012-12-31");
        System.out.println("End: " + end);

        List<DateTime> between = getDateRange(start, end);
        for (DateTime d : between) {
            System.out.println(" " + d);
        }
    }
}
Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
Matteo
  • 1,367
  • 7
  • 25
  • Just messing with the code above, I kinda agree with ur view. I never used calendar before but it is not so nice. – sys_debug Nov 17 '11 at 11:48
  • This is really coooool sooooo thanks verrrrrry much ;) – sys_debug Nov 17 '11 at 14:12
  • FYI, the *Joda-Time* project is now in maintenance mode. It’s main creator, Stephen Colebourne, went on to found and lead the JSR 310 project, implemented as the *java.time* classes built into Java 8 and later. – Basil Bourque Jul 24 '19 at 17:17
7

tl;dr

Year year = Year.of ( 2012 ) ;  // Represent an entire year.

year
.atDay( 1 )                     // Determine the first day of the year. Returns a `LocalDate` object.
.datesUntil(                    // Generates a `Stream<LocalDate>`.
    year
    .plusYears( 1 )             // Returns a new `Year` object, leaving the original unaltered. 
    .atDay( 1 )                 // Returns a `LocalDate`.
)                               // Returns a `Stream<LocalDate>`.
.forEach(                       // Like a `for` loop, running through each object in the stream.
    System.out :: println       // Each `LocalDate` object in stream is passed to a call of `System.out.println`.
)
;

java.time

The other Answers are outmoded as of Java 8.

The old date-time classes bundled with earlier versions of Java have been supplanted with the java.time framework built into Java 8 and later. See Tutorial.

LocalDate (date-only)

If you care only about the date without the time-of-day, use the LocalDate class. The LocalDate class represents a date-only value, without time-of-day and without time zone.

LocalDate start = LocalDate.of( 2016 , 1 , 1 ) ;
LocalDate stop = LocalDate.of( 2016 , 1 , 23 ) ;

To get the current date, specify a time zone. For any given moment, today’s date varies by time zone. For example, a new day dawns earlier in Paris than in Montréal.

LocalDate today = LocalDate.now( ZoneId.of( "America/Montreal" ) );

We can use the isEqual, isBefore, and isAfter methods to compare. In date-time work we commonly use the Half-Open approach where the beginning of a span of time is inclusive while the ending is exclusive.

List<LocalDate> localDates = new ArrayList<>();
LocalDate localDate = start;
while ( localDate.isBefore( stop ) ) {
    localDates.add( localDate );
    // Set up the next loop.
    localDate = localDate.plusDays( 1 );
}

LocalDate::datesUntil

You can obtain a stream of LocalDate objects.

Stream< LocalDate > dates = start.datesUntil( stop ) ;
dates.forEach( System.out::println ) ;

LocalDateRange

If doing much of this work, add the ThreeTen-Extra library to your project. This gives you the LocalDateRange class to represent your pair of start and stop LocalDate objects.

Instant (date-time)

If you have old java.util.Date objects, which represent both a date and a time, convert to the Instant class. An Instant is a moment on the timeline in UTC.

Instant startInstant = juDate_Start.toInstant();
Instant stopInstant = juDate_Stop.toInstant();

From those Instant objects, get LocalDate objects by:

  • Applying the time zone that makes sense for your context to get ZonedDateTime object. This object is the very same moment on the timeline as the Instant but with a specific time zone assigned.
  • Convert the ZonedDateTime to a LocalDate.

We must apply a time zone as a date only has meaning within the context of a time zone. As we said above, for any given moment the date varies around the world.

Example code.

ZoneId zoneId = ZoneId.of( "America/Montreal" );
LocalDate start = ZonedDateTime.ofInstant( startInstant , zoneId ).toLocalDate();
LocalDate stop = ZonedDateTime.ofInstant( stopInstant , zoneId ).toLocalDate();
Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
  • 1
    I think the while condition should be `while(localDate.isBefore( stop ))`, as the `start` variable is not updated. – Leonidas K Aug 18 '17 at 12:09
  • @LeonidasK Fixed. Thanks. FYI, on Stack Overflow, you are welcome to edit an Answer yourself to fix such issues. – Basil Bourque Aug 18 '17 at 15:42
7

You could use this function:

public static Date addDay(Date date){
   //TODO you may want to check for a null date and handle it.
   Calendar cal = Calendar.getInstance();
   cal.setTime (date);
   cal.add (Calendar.DATE, 1);
   return cal.getTime();
}

Found here. And what is the reason of fail? Why you think that your code is failed?

Community
  • 1
  • 1
Sergey Vedernikov
  • 7,609
  • 2
  • 25
  • 27
  • it fails on one line tmpDate = tmpDate.getTime() + MILLIS_IN_DAY); because getTime() isn't there :) But thanks will try ur code then output to the list :) – sys_debug Nov 17 '11 at 11:41
2

You can use joda-time.

Days.daysBetween(fromDate, toDate);

Found at joda-time homepage.

similar question in stackoverflow with some good answers.

Community
  • 1
  • 1
mbde
  • 171
  • 1
  • 7
1

Look at the Calendar API, particularly Calendar.add().

Matthew Farwell
  • 60,889
  • 18
  • 128
  • 171