0

I want to add a month to a date...

But I want to assign the result to a new variable without changing the original date. I'd like to do this the standard way, which seems to be using Calendar.add() but that method changes the Calendar object used for calculation.

So I'm wondering what the "proper" thing to do here is - should I use Object.clone() and cast back to Calendar? Instinctively this seems a bit horrible and wrong. Alternatively should I create a new Calendar object from the original one using a syntax like:

Calendar newCalendar = Calendar.getInstance();
newCalendar.setTime(originalCalendar.getTime());

Seems pretty horrible too... surely there must be an easier way - please somebody tell me I'm missing something!

(...but please don't tell me to use Joda Time or Java 8 - I can't due to project constraints.)

Steve Chambers
  • 37,270
  • 24
  • 156
  • 208

5 Answers5

3

Calendar is not a pretty library so you shouldn't expect it to be.

AFAIK, Java 8 will have a new Date/Time library based on JodaTime. ;)

please don't tell me to use Joda Time - I can't due to project constraints

In that case, just learn to enjoy using Calendar and its quirks.

mikej
  • 65,295
  • 17
  • 152
  • 131
Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • I'm not expecting Calendar to be pretty but given it's part of the core language am just wondering the standard way people do this - it must be so common! – Steve Chambers Dec 12 '12 at 14:44
  • AFAIK, Usually Calendar is treated as mutable, rather than take copies. I am not saying thats a good idea, but it's the way the API was designed 15 years ago. – Peter Lawrey Dec 12 '12 at 15:36
  • 1
    Thanks, points given - yours is probably the most informative answer even though it wasn't quite what I'd hoped. – Steve Chambers Dec 12 '12 at 21:23
1

In case it helps anyone or anyone has any comments here's the code I ended up with:

/**
 * Get a new date/time by adding the specified number at the specified granularity
 * (day/weeks/months etc.) to a date/time.
 * @param dateTime
 *            Date/time to add to
 * @param field
 *            The calendar field representing granularity (day/weeks/months etc.)
 * @param amount
 *            Amount to be added
 * @return A new date/time from performing the calculation
 */
public static Calendar add(final Calendar dateTime, final int field, final int amount) {
    // Clone the date/time so the original one isn't changed
    Calendar newDateTime = Calendar.getInstance();
    Date dateTimeAsMillis = dateTime.getTime();
    newDateTime.setTime(dateTimeAsMillis);

    // Add the specified amount at the specified granularity
    newDateTime.add(field, amount);

    return newDateTime;
}
Steve Chambers
  • 37,270
  • 24
  • 156
  • 208
  • `Calendar` should have been using `Enum` for the fields. But as @Peter Lawrey said, the API was designed 15 years ago. – mike Aug 08 '13 at 11:57
0

What is wrong with

Calendar resultCalendar = originalCalendar.clone(); // Or any other way of creating a copy
resultCalendar.add(...);

?

Germann Arlington
  • 3,315
  • 2
  • 17
  • 19
  • Hmmm, clone() may be the answer but it just seems a little bit wrong to me, especially when I came across this thread: http://stackoverflow.com/questions/2499113/quickest-way-to-clone-a-gregoriancalendar – Steve Chambers Dec 12 '12 at 14:42
  • This is an argument in favour of implementing `copy constructors` in all/many/few classes. – Germann Arlington Dec 12 '12 at 14:46
  • Maybe true but unfortunately I'm not able to rewrite the Java language (incidentally this is for an external customer and as such I'm confined to using Java 1.6). – Steve Chambers Dec 12 '12 at 14:55
0

If you cannot use Joda-Time and restricted to the standard Date/Calendar API then I would suggest the following:

Calendar calendar = Calendar.getInstance();
Date originalDate = calendar.getTime();

calendar.add(Calendar.MONTH, 1);
Date newDate = calendar.getTime();

calendar.setTime(originalDate);

This will back up you current date, then use calendar to calculate current date + 1 month, and then restore the original settings to the calendar.

Andrii Polunin
  • 1,306
  • 11
  • 15
  • Yes, I prefer this to clone() but was hoping there'd be a way with fewer lines of code! As Peter Lawrey pointed out, Calendar's certainly "not pretty" if this is the way people do it... – Steve Chambers Dec 12 '12 at 14:46
0

If u really don't want to clone a new calendar object, U might retrieve how many days in the current month and then calculate how much time need to span to the next month.

At this time u can just setTime(currentCalendar.getTime() + spanTime);

YiFan Wu
  • 123
  • 5