-3

I am working in an integrated environment (IBM Process Server) and I am not able to import anything, can only use standard java functionality.

How can I add x number of months to a given date?

ppeterka
  • 20,583
  • 6
  • 63
  • 78
antonpug
  • 13,724
  • 28
  • 88
  • 129

4 Answers4

2

Given that you have Date imported by default, you can add a number of months to the date object by the following:

public void addMonths(Date date, int numMonths){
    date.setMonth((date.getMonth() - 1 + numMonths) % 12 + 1);
}

NOTE

You can use external classes from Java SE by using their full package name. i.e., even if you cannot add import java.util.Calendar; to the top of you .java file, you can still create a calendar object by executing java.util.Calendar cal = java.util.Calendar.getInstance();

Jayamohan
  • 12,734
  • 2
  • 27
  • 41
ewok
  • 20,148
  • 51
  • 149
  • 254
  • 2
    The Date.setMonth(int) method is deprecated almost since Java began. Consider whether there will be any disadvantage to using deprecated methods (even if it's only seeing a stream of warnings generated by your compiler). – Bobulous Jul 20 '12 at 18:14
  • @user1515834 true. Most of `java.util.Date` was deprecated and replaced by `java.util.Calendar`, but as we've seen, using `java.util.Calendar` seems to be a problem. – ewok Jul 20 '12 at 18:22
0

@ewok's answer does not work always when going past the year end, only with numMonths set to values lower or equal to the months until next January:

SSCCE:

public static  void main(String[] args) {
  for(int i=0;i<10; i++) {
    Date date = new Date();
    Date updated = (Date)date.clone();
    addMonths(updated, i);
    System.out.println(" original: " + date+  " adding " +i+ " months: " + updated);
  }
}

public static void addMonths(Date date, int numMonths){
  date.setMonth((date.getMonth() - 1 + numMonths) % 12 + 1);
}

Output:

original: Sat Aug 24 14:02:17 CEST 2013 adding 0 months: Sat Aug 24 14:02:17 CEST 2013
original: Sat Aug 24 14:02:17 CEST 2013 adding 1 months: Tue Sep 24 14:02:17 CEST 2013
original: Sat Aug 24 14:02:17 CEST 2013 adding 2 months: Thu Oct 24 14:02:17 CEST 2013
original: Sat Aug 24 14:02:17 CEST 2013 adding 3 months: Sun Nov 24 14:02:17 CET 2013
original: Sat Aug 24 14:02:17 CEST 2013 adding 4 months: Tue Dec 24 14:02:17 CET 2013
original: Sat Aug 24 14:02:17 CEST 2013 adding 5 months: Fri Jan 24 14:02:17 CET 2014
original: Sat Aug 24 14:02:17 CEST 2013 adding 6 months: Sun Feb 24 14:02:17 CET 2013
original: Sat Aug 24 14:02:17 CEST 2013 adding 7 months: Sun Mar 24 14:02:17 CET 2013
original: Sat Aug 24 14:02:17 CEST 2013 adding 8 months: Wed Apr 24 14:02:17 CEST 2013
original: Sat Aug 24 14:02:17 CEST 2013 adding 9 months: Fri May 24 14:02:17 CEST 2013

Notice the February, March, etc dates are back in 2013! The code is flawed because of the strange arithmetics... setMonth handles values > 12 too...

Corrected (though still using the deprecated method...):

      date.setMonth((date.getMonth() + numMonths) );

Output:

original: Sat Aug 24 14:13:09 CEST 2013 adding 0 months: Sat Aug 24 14:13:09 CEST 2013
original: Sat Aug 24 14:13:09 CEST 2013 adding 1 months: Tue Sep 24 14:13:09 CEST 2013
original: Sat Aug 24 14:13:09 CEST 2013 adding 2 months: Thu Oct 24 14:13:09 CEST 2013
original: Sat Aug 24 14:13:09 CEST 2013 adding 3 months: Sun Nov 24 14:13:09 CET 2013
original: Sat Aug 24 14:13:09 CEST 2013 adding 4 months: Tue Dec 24 14:13:09 CET 2013
original: Sat Aug 24 14:13:09 CEST 2013 adding 5 months: Fri Jan 24 14:13:09 CET 2014
original: Sat Aug 24 14:13:09 CEST 2013 adding 6 months: Mon Feb 24 14:13:09 CET 2014
original: Sat Aug 24 14:13:09 CEST 2013 adding 7 months: Mon Mar 24 14:13:09 CET 2014
original: Sat Aug 24 14:13:09 CEST 2013 adding 8 months: Thu Apr 24 14:13:09 CEST 2014
original: Sat Aug 24 14:13:09 CEST 2013 adding 9 months: Sat May 24 14:13:09 CEST 2014

Things to consider

  • Last days of months, from the Java doc of setMonth():

    Sets the month of this date to the specified value. This Date object is modified so that it represents a point in time within the specified month, with the year, date, hour, minute, and second the same as before, as interpreted in the local time zone. If the date was October 31, for example, and the month is set to June, then the new date will be treated as if it were on July 1, because June has only 30 days.

  • Still deprecated - Solving the problem properly would be overly time consuming however (exceptional cases, leap days, leap seconds, whatever), not to mention total reinvention of the wheel... Maybe trimming Calendar to the bare minimum, and pasting it into the code would solve it - but even that is not worth the hassle...

  • Should definitely try the second approach what @ewok suggested, the fully qualified classname thing.

ppeterka
  • 20,583
  • 6
  • 63
  • 78
0

If you want to implement without calendar use @ewok suggestion if working with deprecated method a problem then use the following code:

SimpleDateFormat dt1 = new SimpleDateFormat("yyyy-MM-dd");  //Date format
    SimpleDateFormat dt = new SimpleDateFormat("MM");
    Date date = dt1.parse("2013-12-31");
    int dm=0;
    int m = Integer.parseInt(dt.format(date));
    switch(m){
        case 2:
            m = 27;
        break;
        case 4:
        case 6:
        case 9:
        case 11:
            m = 29;
        break;
        default:
            m = 30;
        break;
    }// Closing switch block
    long month = Math.round(1000*60*60*24.25*m);
    long oneMonthTime =  date.getTime()+month;
    System.out.println(dt1.format(oneMonthTime));

This code is not for leap year. I know its non perfect one but still working code.

Santhoshle
  • 593
  • 5
  • 11
-1

tl;dr

myJavaUtilDate.toInstant()                      // Convert troublesome legacy `java.util.Date` object to a modern java.time object, `Instant`.
    .atZone( ZoneId.of( "Pacific/Auckland" ) )  // Adjust that `Instant` object from UTC to a particular time zone thereby instantiating a `ZonedDateTime` object, to determine dates.
    .plus( Period.ofMonths( 6 ) )               // Add six months represented by a `Period` to instantiate another `ZonedDateTime` object.

java.time

The java.time classes are built into Java 8, Java 9, and later. These supplant the troublesome old date-time classes such as Date and Calendar.

If you must inter-operate with an existing Date object, convert to java.time. The equivalent is Instant. The Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds (up to nine (9) digits of a decimal fraction). Convert using new methods added to the old classes.

Instant instant = myJavaUtilDate.toInstant() ;

An Instant is a moment in UTC. Adding six months requires a date. A time zone is crucial in determining a date. For any given moment, the date varies around the globe by zone. For example, a few minutes after midnight in Paris France is a new day while still “yesterday” in Montréal Québec.

Specify a proper time zone name in the format of continent/region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 3-4 letter pseudo-zones such as EST or IST as they are not true time zones, not standardized, and not even unique(!).

ZoneId z = ZoneId.of( "America/Montreal" ) ;

Adjust your Instant into that time zone, applying a ZoneId to get a ZonedDateTime object.

ZonedDateTime zdt = instant.atZone( z ) ;

Define six months as a Period.

Period p = Period.ofMonths( 6 ) ;

Add that Period object to generate a new ZonedDateTime object.

ZonedDateTime later = zdt.plus( p ) ;

See this code run live at IdeOne.com.

instant.toString(): 2018-01-31T06:26:34.580Z

zdt.toString(): 2018-01-31T01:26:34.580-05:00[America/Montreal]

p.toString(): P6M

later.toString()2018-07-31T01:26:34.580-04:00[America/Montreal]

If you need to get back to a value in UTC, extract a Instant.

Instant instant = later.toInstant() ;

If you need a Date, convert. But try to avoid this class if possible.

Date d = Date.from( instant ) ;

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

LocalDate ld = LocalDate.of( 2018 , Month.JANUARY , 23 ) ;  // January 23, 2018.
LocalDate later = ld.plusMonths( 6 ) ;

About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

Where to obtain the java.time classes?

The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154