Harsha
Harsha

Reputation: 3578

How to handle dates in java

I have a java programe which I can set a date in yyyy-MM-dd and I can get next and previous dates from it. following methods do the work,,

public void setDate(String date) {
        StringTokenizer st = new StringTokenizer(date, "-");
        year = Integer.parseInt(st.nextToken());
        monthNo = Integer.parseInt(st.nextToken()) - 1;
        day = Integer.parseInt(st.nextToken());
        date = year + "-" + monthNo + "-" + day;        
    }    

public String getPreviousMonth(boolean maxDate) {
            Calendar calendar = Calendar.getInstance();

            if (maxDate) {
                calendar.set(year, monthNo, 1);
                int maxD = calendar.getActualMaximum(calendar.DAY_OF_MONTH);
                 calendar.set(year, monthNo, maxD);
            } else {
                calendar.set(year, monthNo, day);
            }

            if (monthNo == 0) {
                calendar.add(calendar.MONTH, -1);
            } else {
                calendar.add(calendar.MONTH, -1);
            }
            String date = (calendar.get(calendar.YEAR)) + "-" + (calendar.get(calendar.MONTH) + 1) + "-" + calendar.get(calendar.DAY_OF_MONTH);
            calendar.clear();
            return date;
        }

        public String getNextMonth(boolean maxDate) {
            Calendar calendar = Calendar.getInstance();

            if (maxDate) {
                calendar.set(year, monthNo, 1);
                int maxD = calendar.getActualMaximum(calendar.DAY_OF_MONTH);
                calendar.set(year, monthNo, maxD);
            } else {
                calendar.set(year, monthNo, day);
            }
            if (monthNo == 11) {
                calendar.add(calendar.MONTH, 1);
            } else {
                calendar.add(calendar.MONTH, 1);
            }




    public String getCurrentMonth(boolean maxDate){
            Calendar calendar = Calendar.getInstance();
            if (maxDate) {
                calendar.set(year, monthNo, 1);
                int maxD = calendar.getActualMaximum(calendar.DAY_OF_MONTH);
                calendar.set(year, monthNo, maxD);
            } else {
                calendar.set(year, monthNo, day);
            }
            String date = (calendar.get(calendar.YEAR)) + "-" + (calendar.get(calendar.MONTH) + 1) + "-" + calendar.get(calendar.DAY_OF_MONTH);
            calendar.clear();
            return date;
        }

When I set the date to January and February, it gives me the correct output but if I select another month other than January and February I can't get the correct day, followings are some results,

this is OK
2012-1-31 - current month
2011-12-31 - previous month
2012-2-29 - next month

2012-2-29 current month
2012-1-29 previous month ***day should be 31
2012-3-29 next month ***day should be 31

this is OK
2011-12-31 current month
2011-11-30 previous month
2012-1-31 next month

2011-11-30 current month
2011-10-30 previous month *** this should be 31
2011-12-30 next month *** this should be 31

this is OK
2011-12-31 current month
2011-11-30 previous month
2012-1-31 next month

Please tell me where am I wrong...

Upvotes: 2

Views: 2591

Answers (3)

Basil Bourque
Basil Bourque

Reputation: 338326

tl;dr

Use java.time.LocalDate rather than the terribly-flawed legacy class Calendar.

LocalDate
    .parse( "2025-01-23" )  // Parse text in standard ISO 8601 format, YYYY-MM-DD. 
    .plusDays( 1 ) 
    .minusDays( 2 )
    .minusMonths( 1 )
    .plusMonths( 2 )
    .withDayOfMonth( 1 )
    .toString()             // Generate text in standard ISO 8601 format.

See that code run at Ideone.com.

2025-02-01

Avoid legacy classes

The terribly-flawed legacy classes Date, Calendar, SimpleDateFormat, etc. were years ago supplanted by the modern java.time classes defined in JSR 310, built into Java 8 and later.

java.time

Your input text complies with ISO 8601 standard format, YYYY-MM-DD. The java.time classes use ISO 8601 formats by default when parsing/generating text. So no need to specify a formatting pattern.

LocalDate

To represent a date-only value, without time-of-day, without time zone, use LocalDate.

String input = "2025-01-23" ;
LocalDate ld = LocalDate.parse( input ) ;

To perform date-math, use the minus & plus methods.

LocalDate dayBefore = ld.minusDays( 1 ) ;
LocalDate dayAfter = ld.plusDays( 1 ) ;

Move to another month.

LocalDate monthBefore = ld.minusMonths( 1 ) ;
LocalDate monthAfter = ld.plusMonths( 1 ) ;

Get first & last dates of the month.

LocalDate firstOfMonth = ld.withDayOfMonth( 1 ) ;
LocalDate lastOfMonth = ld.withDayOfMonth( ld.lengthOfMonth() ) ;

YearMonth

If you work frequently with the concept of month, use YearMonth class.

YearMonth ym = YearMonth.from( ld ) ;
LocalDate firstOfMonth = ym.atDay( 1 ) ;
LocalDate endOfMonth = ym.atEndOfMonth() ;

Upvotes: 1

Alex Abdugafarov
Alex Abdugafarov

Reputation: 6392

The problem was that you retrieved maximum amount of days in current month BEFORE actually changing the month.
Here how should it look.

public String getNextMonth(boolean maxDate) {
    Calendar calendar = Calendar.getInstance();
    calendar.set(year, monthNo, 1);
    calendar.add(Calendar.MONTH, 1);
    if (maxDate) {
        int maxD = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
        calendar.set(Calendar.DAY_OF_MONTH, maxD);
    } else {
        calendar.set(Calendar.DAY_OF_MONTH, day);
    }
    String date = (calendar.get(Calendar.YEAR)) + "-" + (calendar.get(Calendar.MONTH) + 1) + "-" + calendar.get(Calendar.DAY_OF_MONTH);
    calendar.clear();
    return date;
}

Upvotes: 1

Husain Basrawala
Husain Basrawala

Reputation: 1751

Fixing getNextMonth for you. Same thing needs to be done for getPreviousMonth. See the comments inline with code below:

  public String getNextMonth(boolean maxDate) {
        Calendar calendar = Calendar.getInstance();

        if (maxDate) {
            calendar.set(year, monthNo, 1);
            /* Move these two lines to end of method.
            int maxD = calendar.getActualMaximum(calendar.DAY_OF_MONTH);
            calendar.set(year, monthNo, maxD);
             */
        } else {
            calendar.set(year, monthNo, day);
        }
        //Not sure why have you used if/else. Both are doing the same thing
        if (monthNo == 11) {
            calendar.add(calendar.MONTH, 1);
        } else {
            calendar.add(calendar.MONTH, 1);
        }
        //here i.e. After you have calculated your next month.
        int maxD = calendar.getActualMaximum(calendar.DAY_OF_MONTH);
        calendar.set(year, monthNo, maxD);

    }

Upvotes: 3

Related Questions