Fix bugs in interval-to-time conversion: HAVE_INT64_TIMESTAMP case did not
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 16 Jun 2003 18:56:45 +0000 (18:56 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 16 Jun 2003 18:56:45 +0000 (18:56 +0000)
work at all, and neither case behaved sanely for negative intervals.

src/backend/utils/adt/date.c

index bd9653d0fa695bed6da458de73703251726f9a97..fa03b577891e5b062925d9cc3ab3958dad68677d 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/utils/adt/date.c,v 1.82 2003/05/12 23:08:50 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/utils/adt/date.c,v 1.83 2003/06/16 18:56:45 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1066,6 +1066,11 @@ time_interval(PG_FUNCTION_ARGS)
 
 /* interval_time()
  * Convert interval to time data type.
+ *
+ * This is defined as producing the fractional-day portion of the interval.
+ * Therefore, we can just ignore the months field.  It is not real clear
+ * what to do with negative intervals, but we choose to subtract the floor,
+ * so that, say, '-2 hours' becomes '22:00:00'.
  */
 Datum
 interval_time(PG_FUNCTION_ARGS)
@@ -1074,15 +1079,23 @@ interval_time(PG_FUNCTION_ARGS)
    TimeADT     result;
 
 #ifdef HAVE_INT64_TIMESTAMP
+   int64       days;
+
    result = span->time;
-   if ((result >= INT64CONST(86400000000))
-       || (result <= INT64CONST(-86400000000)))
-       result -= (result / INT64CONST(1000000) * INT64CONST(1000000));
+   if (result >= INT64CONST(86400000000))
+   {
+       days = result / INT64CONST(86400000000);
+       result -= days * INT64CONST(86400000000);
+   }
+   else if (result < 0)
+   {
+       days = (-result + INT64CONST(86400000000-1)) / INT64CONST(86400000000);
+       result += days * INT64CONST(86400000000);
+   }
 #else
-   Interval    span1;
-
    result = span->time;
-   TMODULO(result, span1.time, 86400e0);
+   if (result >= 86400e0 || result < 0)
+       result -= floor(result / 86400e0) * 86400e0;
 #endif
 
    PG_RETURN_TIMEADT(result);