last date of previous month returning 30 days for May

Viewed 256

I am using the below code to retrieve the last day in the previous month - Ex: May. But it is returning 30 days instead of 31.

The code given below

package net.vcmg.date;
import java.util.Calendar;
import java.util.Date;

import org.apache.commons.lang.time.DateUtils;

public class LastDayPreviousMonth {
    public static void main(String[] args) {
        Date lastDateOfPreviousMonth = addMonths(lastDayOfTheMonth(today()), -1);
        System.out.println("lastDateOfPreviousMonth: "+lastDateOfPreviousMonth);

    }

    //the below method is from Utils.java
    public static Date lastDayOfTheMonth(Date d) {
           Calendar cal = Calendar.getInstance();
           cal.setTime(d);
           int actualMax = cal.getActualMaximum(Calendar.DAY_OF_MONTH);
           cal.set(Calendar.DAY_OF_MONTH, actualMax);
           return cal.getTime();
    }

    public static Date addMonths(Date date, int numMonths)
    {
        return DateUtils.addMonths(date, numMonths);
    }

    public static Date today()
    {
        return truncDate(now());
    }

    public static Date now()
    {
        // will cut-off milliseconds
        return new Date( (System.currentTimeMillis()/1000) * 1000);
    }

    public static Date truncDate (Date date) {
        return DateUtils.truncate(date, Calendar.DATE);
    }

}

Here, when i call the lastDateOfPreviousMonth in the main method, it is returning 30 days alone. Not the 31 , May contains 31 days actually. Please help.

3 Answers

Java 8

If you are not constraint to use the old Date it will be better to use the new java.time.LocalDate

LocalDate previousMonth = LocalDate.now().minusMonths(1);

LocalDate start = previousMonth.withDayOfMonth(1);
LocalDate end = previousMonth.withDayOfMonth(previousMonth.lengthOfMonth());
System.out.println(start);
System.out.println(end);

Output

2019-05-01
2019-05-31

Edit

For your implementation, change the order of methods

  1. addMonths - get the current date and provide the previous month addMonths(new Date(), -1)
  2. lastDayOfTheMonth - get the last day of the previous month lastDayOfTheMonth(addMonths(new Date(), -1))
Date lastDateOfPreviousMonth = lastDayOfTheMonth(addMonths(new Date(), -1));

Output

lastDateOfPreviousMonth: Fri May 31 10:46:13 EEST 2019

Try this:

public static void main(String[] args) {
        Date lastDateOfPreviousMonth = lastDayOfTheMonth(addMonths(today(), -1));
        System.out.println("lastDateOfPreviousMonth: " + lastDateOfPreviousMonth);

    }

When you call lastDayOfTheMonth for today() day will be 30. And after minus one month result expected will be 30, not 31.

It’s a logical error in the way you have thought out your program/algorithm. You are first finding the last day of the month, in this case June 30. You are then subtracting 1 month. That gives May 30 regardless of the fact that there are 31 days in May (it’s not explicit from the documentation of DateUtils.addMonths that it works this way, but it uses the poorly designed and outdated Calendar class internally, so this is what we should expect).

Instead do things in the opposite order. First find the previous month:

YearMonth lastMonth = YearMonth.now(ZoneId.of("Asia/Kolkata")).minusMonths(1);

2019-05

Since the new month doesn’t begin at the same point in time in all time zones, I recommend that you state your desired time zone as shown.

Only then find the last day of the month:

LocalDate lastDayOfLastMonth = lastMonth.atEndOfMonth();

2019-05-31

Avoid Date and Calendar

I recommend you don’t use Date and Calendar. Those classes are poorly designed and long outdated. Instead use LocalDate and other classes from java.time, the modern Java date and time API. This will also save you from the external dependency on Apache DateUtils since its functionality is generally built into the modern classes.

Links

Related