-3

I wish to add one day to a given date.If i pass 2018-08-05,the below method returns 2018-08-06 which is expected. But if the pass the last date of the month -2018-08-31,it returns 2018-08-01 instead of expected result 2018-09-01.

DateFormat format = new SimpleDateFormat("yyyy-mm-dd", Locale.ENGLISH);
Date date = null;
try {
    date = format.parse("2018-08-31");
} catch (ParseException e) {
}
Calendar cal = Calendar.getInstance();
cal.setTime(date);
cal.add(Calendar.DATE ,1);
return format.format(cal.getTime());
eshaa
  • 386
  • 2
  • 7
  • 26
  • 6
    Your format is wrong, it should be `yyyy-MM-dd` with uppercase `M`. If you are on Java 8, though, then don't use the outdated `Date`/`Calendar`, [use `LocalDate`](https://stackoverflow.com/a/20906602/3178068). – TiiJ7 Sep 08 '18 at 10:07

3 Answers3

5

You're using the old calendar/date API. This API is quite bad (it does weird things and does not accurately model how dates actually work).

It has been replaced with the new java.time API. I strongly suggest you use that instead. If you're on java7 or below, you can use the 'JSR310-backport' library to your dependency list to use this API. (JSR310 is the name for this addition to java).

In java.time, you'd do:

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;

public class Test {
  public static void main(String[] args) {   
    DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd");
    LocalDate date = LocalDate.parse("2018-08-31", fmt);
    System.out.println(fmt.format(date.plusDays(1)));

    // yyyy-MM-dd so happens to be the default for LocalDate, so...
    // we can make it a lot simpler:
    date = LocalDate.parse("2018-08-31");
    System.out.println(date.plusDays(1));
  }
}
rzwitserloot
  • 85,357
  • 5
  • 51
  • 72
0

The bug is in the pattern of your SimpleDateFormat which you use for input and output. This dual-use masks the error:

public class Main {
    public static void main(String[] args) throws Exception {
        DateFormat format = new SimpleDateFormat("yyyy-mm-dd", Locale.ENGLISH);
        Date date = format.parse("2018-08-31");

        System.out.println("format: " + format.format(date) +", real: " + date);

        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.DATE ,1);

        System.out.println("format: " + format.format(cal.getTime()) +", real: " + cal.getTime());
    }
}

This gives you:

format: 2018-08-31, real: Wed Jan 31 00:08:00 CET 2018
format: 2018-08-01, real: Thu Feb 01 00:08:00 CET 2018

Using the right pattern yyyy-MM-dd produces the right answer:

format: 2018-08-31, real: Fri Aug 31 00:00:00 CEST 2018
format: 2018-09-01, real: Sat Sep 01 00:00:00 CEST 2018

Since the new and the old Java-Time API use the same patterns, simply adopting the new API will not help in this case.

A.H.
  • 63,967
  • 15
  • 92
  • 126
  • Correction: Adopting the modern API will help the first bit of the way since it will throw an exception and you will thereby be notified that you have got an error in your code. – Ole V.V. Sep 11 '18 at 09:47
-1
DateFormat format = new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH);
Date date = null;
try {
date = format.parse("2018-08-31");
} catch (ParseException e) {
}
Calendar cal = new GregorianCalendar();
cal.setTime(date);
cal.setTimeInMillis(cal.getTimeInMillis() + 86400000); //86400000ms = 1 day
return format.format(cal.getTime());
Ali ZD
  • 85
  • 9