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?
2
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.
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.
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
- increment month by one unit beyond the month, adjusting the year as necessary;
- change day of month to one;
- Then subtract one day unit;
2