8

I've writing a date-time library, and need to implement the addition of a duration to a date-time.

If I add a 1 month duration: P1M to the 31st March 2012: 2012-03-31, does the standard define what the result is?

Because the resulting date (31st April) does not exist, there are at least two options:

  • Fall back to the last day of the resulting month. This is the approach currently taken by the ThreeTen API, the (alpha) reference implementation of JSR-310:
ZonedDateTime date = ZonedDateTime.parse("2012-03-31T00:00:00Z");
Period duration = Period.parse("P1M");
System.out.println(date.plus(duration).toString());

// 2012-04-30T00:00Z
  • Carry the extra day to the next month. This is the approach taken by the DateTime class in PHP:
$date = new DateTime('2012-03-31T00:00:00Z');
$duration = new DateInterval('P1M');
echo $date->add($duration)->format('c');

// 2012-05-01T00:00:00+00:00

I'm surprised that two date-time libraries contradict on this point, so I'm wondering whether the standard defines the result of this operation?

BenMorel
  • 283
  • 2
  • 9
  • 6
    Counting with dates can introduce remarkable behaviour: March 31st + 2 months can be May 31st while ((March 31st)+ 1 month) + 1 month) can be either may 30th or June 1st but never May 31st – Pieter B Dec 19 '12 at 12:49
  • 1
    You can even land on a time that never happened (The hour you leap ahead for daylight savings) – brian Dec 19 '12 at 14:23

3 Answers3

5

I work in financial domain, and I understand there are different conventions to follow these corner cases.

Follow Wikipedia article Day Count Convention for details.

ISO_8601 does not have any specific value for month as duration, but the link The Mathematics of the ISO 8601 Calendar suggest month as 30.6, year as 365.25, with additional handling for leap years.

gnat
  • 21,442
  • 29
  • 112
  • 288
Tilak
  • 239
  • 2
  • 9
1

That's an edge case. I got no specifications to back my statement up, but...

You should use the last date of the next month. Else you have added two months and not one month.

jgauffin
  • 4,512
  • 21
  • 33
0

Adding by months makes no sense. You should only add by days or fractions of days. Even years can be problematic when dealing with leap days. Did you mean one year or 365 days or 366 days?

You should establish relative addition. Are you looking for end of the month, first of the month, or last workday of the month?

For end of month I use: To calculate the last day of April

  1. increment month by one unit beyond the month, adjusting the year as necessary;
  2. change day of month to one;
  3. Then subtract one day unit;
mhoran_psprep
  • 2,328
  • 2
  • 16
  • 14
  • 4
    So it should be illegal to represent the problem domain concept _"on the same day next month"_ in code? Or only inconvenient? – Useless Dec 19 '12 at 14:07
  • 1
    Actually, even adding days isn't always clear. Does adding "a day" to 11:30pm on the Saturday before time springs forward advance 24 hours (to 12:30am Monday) or 23 hours (to 11:30pm Sunday)? – supercat Jul 26 '14 at 00:12