Index: doc/src/sgml/func.sgml
===================================================================
RCS file: /cvsroot/pgsql/doc/src/sgml/func.sgml,v
retrieving revision 1.382
diff -c -c -r1.382 func.sgml
*** doc/src/sgml/func.sgml	6 Jun 2007 23:00:35 -0000	1.382
--- doc/src/sgml/func.sgml	18 Jul 2007 03:09:42 -0000
***************
*** 5895,5900 ****
--- 5895,5911 ----
     <literal>CST7CDT</literal>.
    </para>
  
+   <para>
+    Note that when the <function>age</> function operates on multi-month
+    intervals, <productname>PostgreSQL</> adds days to the earlier date
+    until full months can be added.  This yields a different result than
+    adding full months first if the interval crosses from one month to the
+    next.  For example, <literal>age('2004-06-01', '2004-04-30')</> yeilds
+    <literal>1 mon 1 day</> using the <productname>PostgreSQL</> method,
+    while adding the month first would yield <literal>1 mon 2 days</>
+    because May has 31 days, while April has only 30.
+   </para>
+ 
    <sect2 id="functions-datetime-extract">
     <title><function>EXTRACT</function>, <function>date_part</function></title>
  
Index: src/backend/utils/adt/timestamp.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/utils/adt/timestamp.c,v
retrieving revision 1.179
diff -c -c -r1.179 timestamp.c
*** src/backend/utils/adt/timestamp.c	6 Jul 2007 04:15:59 -0000	1.179
--- src/backend/utils/adt/timestamp.c	18 Jul 2007 03:09:44 -0000
***************
*** 3044,3050 ****
  	if (timestamp2tm(dt1, NULL, tm1, &fsec1, NULL, NULL) == 0 &&
  		timestamp2tm(dt2, NULL, tm2, &fsec2, NULL, NULL) == 0)
  	{
! 		fsec = (fsec1 - fsec2);
  		tm->tm_sec = tm1->tm_sec - tm2->tm_sec;
  		tm->tm_min = tm1->tm_min - tm2->tm_min;
  		tm->tm_hour = tm1->tm_hour - tm2->tm_hour;
--- 3044,3051 ----
  	if (timestamp2tm(dt1, NULL, tm1, &fsec1, NULL, NULL) == 0 &&
  		timestamp2tm(dt2, NULL, tm2, &fsec2, NULL, NULL) == 0)
  	{
! 		/* form the symbolic difference */
! 		fsec = fsec1 - fsec2;
  		tm->tm_sec = tm1->tm_sec - tm2->tm_sec;
  		tm->tm_min = tm1->tm_min - tm2->tm_min;
  		tm->tm_hour = tm1->tm_hour - tm2->tm_hour;
***************
*** 3064,3069 ****
--- 3065,3081 ----
  			tm->tm_year = -tm->tm_year;
  		}
  
+ 		/* propagate any negative fields into the next higher field */
+ 		while (fsec < 0)
+ 		{
+ #ifdef HAVE_INT64_TIMESTAMP
+ 			fsec += USECS_PER_SEC;
+ #else
+ 			fsec += 1.0;
+ #endif
+ 			tm->tm_sec--;
+ 		}
+ 
  		while (tm->tm_sec < 0)
  		{
  			tm->tm_sec += SECS_PER_MINUTE;
***************
*** 3158,3163 ****
--- 3170,3176 ----
  	if (timestamp2tm(dt1, &tz1, tm1, &fsec1, &tzn, NULL) == 0 &&
  		timestamp2tm(dt2, &tz2, tm2, &fsec2, &tzn, NULL) == 0)
  	{
+ 		/* form the symbolic difference */
  		fsec = fsec1 - fsec2;
  		tm->tm_sec = tm1->tm_sec - tm2->tm_sec;
  		tm->tm_min = tm1->tm_min - tm2->tm_min;
***************
*** 3178,3183 ****
--- 3191,3207 ----
  			tm->tm_year = -tm->tm_year;
  		}
  
+ 		/* propagate any negative fields into the next higher field */
+ 		while (fsec < 0)
+ 		{
+ #ifdef HAVE_INT64_TIMESTAMP
+ 			fsec += USECS_PER_SEC;
+ #else
+ 			fsec += 1.0;
+ #endif
+ 			tm->tm_sec--;
+ 		}
+ 
  		while (tm->tm_sec < 0)
  		{
  			tm->tm_sec += SECS_PER_MINUTE;
