get startday of month and endday of month using calendar class in Java

Given a year and a month; I want to get two Date Objects. one for startDate of the month and one for the end Date of the month. I have it implemented here and it works. but this looks too verbose, and I am wondering if there is a neat solution to this;

Eg given March 2014, start Date will be March 01 and end Date will be March 31 ( as Date objects with millisecond precision)

public setDates(int month,int year) {

        Calendar calendar = Calendar.getInstance();


        // Use the calendar to get the startDate and endDate of this Invoice.
        calendar.set(Calendar.YEAR, year);
        calendar.set(Calendar.MONTH,month);

        //set start date
        calendar.set(Calendar.DAY_OF_MONTH,
                     calendar.getActualMinimum(Calendar.DAY_OF_MONTH));
        calendar.set(Calendar.HOUR_OF_DAY,
                     calendar.getActualMinimum(Calendar.HOUR_OF_DAY));
        calendar.set(Calendar.MINUTE,
                     calendar.getActualMinimum(Calendar.MINUTE));
        calendar.set(Calendar.SECOND,
                     calendar.getActualMinimum(Calendar.SECOND));
        calendar.set(Calendar.MILLISECOND,
                     calendar.getActualMinimum(Calendar.MILLISECOND));
        this.startDate = calendar.getTime();

        //endDate start date
        calendar.set(Calendar.DAY_OF_MONTH,
                     calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
        calendar.set(Calendar.HOUR_OF_DAY,
                     calendar.getActualMaximum(Calendar.HOUR_OF_DAY));
        calendar.set(Calendar.MINUTE,
                     calendar.getActualMaximum(Calendar.MINUTE));
        calendar.set(Calendar.SECOND,
                     calendar.getActualMaximum(Calendar.SECOND));
        calendar.set(Calendar.MILLISECOND,
                     calendar.getActualMaximum(Calendar.MILLISECOND));
        this.endDate = calendar.getTime();
}
Jon Skeet
people
quotationmark

You can make this code considerably simpler by making some assumptions:

  • The first day of the month is always day 1
  • The minimum hour will always be 0
  • ... etc

You can then find the last millisecond of the month by adding one month and subtracting a millisecond.

So the code could look like this:

// Note year/month reversal: try to consistently use larger units first. It
// makes for a cleaner API.
public setDates(int year, int month, TimeZone zone) {
    Calendar calendar = Calendar.getInstance(zone);

    // Do you really want 0-based months, like Java has? Consider month - 1.
    calendar.set(year, month, 1, 0, 0, 0);
    calendar.clear(Calendar.MILLISECOND);
    startDate = calendar.getTime();

    // Get to the last millisecond in the month
    calendar.add(Calendar.MONTH, 1);
    calendar.add(Calendar.MILLISECOND, -1);
    endDate = calendar.getTime();
}

To use an exclusive upper bound (as I'd recommend), just get rid of the calendar.add(Calendar.MILLISECOND, -1) near the end.

Oh, and I'd thoroughly recommend using Joda Time instead of java.util.Date etc - it's a much cleaner API.

people

See more on this question at Stackoverflow