I\'m looking for standards for Date/Time addition. I haven\'t been able to find any. In particular I\'m hoping to find a spec that defines what should happen when you add a mont
There is no widely accepted standard. The reason for the different implementations is that folks can't agree on what the standard should be. Many popular software systems give answers that no one would expect. Documentation is always necessary, therefore, to tell the user what your system will deliver. You choose a methodology, however, based on what you think most folks will expect.
I think most people on the street would agree that:
The exception comes in accounting, where sometimes a month means 30 days.
EDIT: I asked some folks around here, "If it's March 31 and someone says I'll meet you a month from today, what day are you going to meet them?" Most said, April 30, but a few said April 28 because it's four weeks away. The few were interpreting work schedules and thinking "if we met on this weekday, we'll meet again on the same weekday". Basically, if they met on the last Thursday of the month, and they're due to meet in one month, it'll be on the last Thursday of that month.
So, there ya go. :\
According to the POSIX.1-2001 standard, next month (as in incrementing tm_mon
before calling mktime
) is done by adjusting the values until they fit. So, for example, next month from January 31, 2001 is March 3, 2001. This is because the tm_mday
of 31 isn't valid with tm_mon
of 1 (February), so it is normalized to tm_mon
of 2 (March) and tm_mday
of 3.
The next month from January 31, 2000 is March 2, 2000, because Feb. has 29 days that year. The next month from January, 1 2038 doesn't exist, depending.
The great thing about standards is there are so many to chose from. Check the SQL standard, I bet you can find a different meaning of next month. I suspect ISO 8601 may give you yet another choice. Point is, there are many different behaviors, the meaning of 'next month' is very domain-specific.
edit: I think I've found how SQL-92 handles it, apparently asking for next month from January 31 is an error.
Links:
Try the mysql date function :
SELECT ADDDATE('2011-01-31', INTERVAL 1 MONTH) // 2011-02-28
Input date with leap year
SELECT ADDDATE('2012-01-31', INTERVAL 1 MONTH) // 2012-02-29
Query:
SELECT
ADDDATE(DATE('2010-12-31'), INTERVAL 1 MONTH) 'Dec + Month',
ADDDATE(DATE('2011-01-31'), INTERVAL 1 MONTH) 'Jan + Month',
ADDDATE(DATE('2011-02-28'), INTERVAL 1 MONTH) 'Feb + Month',
ADDDATE(DATE('2011-03-31'), INTERVAL 1 MONTH) 'Mar + Month';
Output:
Dec + Month Jan + Month Feb + Month Mar + Month 2011-01-31 2011-02-28 2011-03-28 2011-04-30
My conclusion:
If you add MONTH, YEAR_MONTH, or YEAR and the resulting date has a day that is larger than the maximum day for the new month, the day is adjusted to the maximum days in the new month
source
Problem here is that it doesn't mention that the month is actually the month from the input date.
In the .NET framework the behavior of System.DateTime.AddMonths is as follows:
The AddMonths method calculates the resulting month and year, taking into account leap years and the number of days in a month, then adjusts the day part of the resulting DateTime object. If the resulting day is not a valid day in the resulting month, the last valid day of the resulting month is used. For example, March 31st + 1 month = April 30th [rather than April 31st].
I've tested how it works exactly:
Console.WriteLine(new DateTime(2008,2,27).AddMonths(1));
Console.WriteLine(new DateTime(2008,2,28).AddMonths(1));
Console.WriteLine(new DateTime(2008,2,29).AddMonths(1));
Console.WriteLine(new DateTime(2011,2,27).AddMonths(1));
Console.WriteLine(new DateTime(2011,2,28).AddMonths(1));
Console.WriteLine(new DateTime(2008,1,30).AddMonths(1));
Console.WriteLine(new DateTime(2008,1,31).AddMonths(1));
Console.WriteLine(new DateTime(2011,1,30).AddMonths(1));
Console.WriteLine(new DateTime(2011,1,31).AddMonths(1));
/* output
3/27/2008 12:00:00 AM
3/28/2008 12:00:00 AM
3/29/2008 12:00:00 AM
3/27/2011 12:00:00 AM
3/28/2011 12:00:00 AM
2/29/2008 12:00:00 AM
2/29/2008 12:00:00 AM
2/28/2011 12:00:00 AM
2/28/2011 12:00:00 AM
*/
I believe the defacto standard is ISO 8601. Unfortunately, there are many ambiguities, for example:
Date arithmetic is not defined
2001-03-30 + P1M = 2001-04-29 (Add 30 days)
2001-03-30 + P1M = 2001-04-30 (Add 1 mon.)
Addition is not commutative or associative
2001-03-30 + P1D + P1M = 2001-04-30
2001-03-30 + P1M + P1D = 2001-05-01
Subtraction is not the inverse of Addition.
Precision of decimal fractions can vary.
The full specification can be found at http://www.iso.org/iso/catalogue_detail.htm?csnumber=26780
I think each product is attempting to adhere to an impossible to implement standard. The ambiguous parts are open to interpretation and so everyone interprets. This is the same standard that opened us up to the Y2K bug!!
Myself, I favor an implementation that converts a date/time to a 1970 based number (UNIX timestamp), performs the calculation and converts back. I believe this is the approach taken by Oracle/MySQL. I am surprised that more attention has not been paid this issue, as it is really important, sometimes critical, in so many applications. Thanks for the question!
Edit: While doing some more reading, I found Joe Celko's thoughts on different date/time representations and standardization HERE.