+
+
true
+ |
+ justify_days(interval)
+ interval
+ Adjust interval so 30-day time periods are represented as months
+ justify_days(interval '30 days')
+ 1 month
+
+
|
justify_hours(interval)
interval
|
- justify_days(interval)
+ justify_interval(interval)
interval
- Adjust interval so 30-day time periods are represented as months
- justify_days(interval '30 days')
- 1 month
+ Adjust interval using justify_days> and justify_hours>, with additional sign adjustments>
+ justify_interval(interval '1 mon -1 hour')
+ 29 days 23:00:00
|
- If you are using both justify_hours> and
- justify_days>, it is best to use justify_hours>
- first so any additional days will be included in the
- justify_days> calculation.
-
-
In addition to these functions, the SQL OVERLAPS> operator is
supported:
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/adt/timestamp.c,v 1.161 2006/03/05 15:58:44 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/timestamp.c,v 1.162 2006/03/06 22:49:16 momjian Exp $
*
*-------------------------------------------------------------------------
*/
PG_RETURN_INTERVAL_P(result);
}
+/*
+ * interval_justify_interval()
+ *
+ * Adjust interval so 'month', 'day', and 'time' portions are within
+ * customary bounds. Specifically:
+ *
+ * 0 <= abs(time) < 24 hours
+ * 0 <= abs(day) < 30 days
+ *
+ * Also, the sign bit on all three fields is made equal, so either
+ * all three fields are negative or all are positive.
+ */
+Datum
+interval_justify_interval(PG_FUNCTION_ARGS)
+{
+ Interval *span = PG_GETARG_INTERVAL_P(0);
+ Interval *result;
+
+#ifdef HAVE_INT64_TIMESTAMP
+ int64 wholeday;
+#else
+ double wholeday;
+#endif
+ int32 wholemonth;
+
+ result = (Interval *) palloc(sizeof(Interval));
+ result->month = span->month;
+ result->day = span->day;
+ result->time = span->time;
+
+#ifdef HAVE_INT64_TIMESTAMP
+ TMODULO(result->time, wholeday, USECS_PER_DAY);
+#else
+ TMODULO(result->time, wholeday, (double) SECS_PER_DAY);
+#endif
+ result->day += wholeday; /* could overflow... */
+
+ wholemonth = result->day / DAYS_PER_MONTH;
+ result->day -= wholemonth * DAYS_PER_MONTH;
+ result->month += wholemonth;
+
+ if (result->month > 0 &&
+ (result->day < 0 || (result->day == 0 && result->time < 0)))
+ {
+ result->day += DAYS_PER_MONTH;
+ result->month--;
+ }
+ else if (result->month < 0 &&
+ (result->day > 0 || (result->day == 0 && result->time > 0)))
+ {
+ result->day -= DAYS_PER_MONTH;
+ result->month++;
+ }
+
+ if (result->day > 0 && result->time < 0)
+ {
+#ifdef HAVE_INT64_TIMESTAMP
+ result->time += USECS_PER_DAY;
+#else
+ result->time += (double) SECS_PER_DAY;
+#endif
+ result->day--;
+ }
+ else if (result->day < 0 && result->time > 0)
+ {
+#ifdef HAVE_INT64_TIMESTAMP
+ result->time -= USECS_PER_DAY;
+#else
+ result->time -= (double) SECS_PER_DAY;
+#endif
+ result->day++;
+ }
+
+ PG_RETURN_INTERVAL_P(result);
+}
+
/*
* interval_justify_hours()
*
#endif
result->day += wholeday; /* could overflow... */
+ if (result->day > 0 && result->time < 0)
+ {
+#ifdef HAVE_INT64_TIMESTAMP
+ result->time += USECS_PER_DAY;
+#else
+ result->time += (double) SECS_PER_DAY;
+#endif
+ result->day--;
+ }
+ else if (result->day < 0 && result->time > 0)
+ {
+#ifdef HAVE_INT64_TIMESTAMP
+ result->time -= USECS_PER_DAY;
+#else
+ result->time -= (double) SECS_PER_DAY;
+#endif
+ result->day++;
+ }
+
PG_RETURN_INTERVAL_P(result);
}
result->day -= wholemonth * DAYS_PER_MONTH;
result->month += wholemonth;
+ if (result->month > 0 && result->day < 0)
+ {
+ result->day += DAYS_PER_MONTH;
+ result->month--;
+ }
+ else if (result->month < 0 && result->day > 0)
+ {
+ result->day -= DAYS_PER_MONTH;
+ result->month++;
+ }
+
PG_RETURN_INTERVAL_P(result);
}
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.400 2006/03/05 15:58:54 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.401 2006/03/06 22:49:16 momjian Exp $
*
* NOTES
* The script catalog/genbki.sh reads this file and generates .bki
DESCR("convert abstime to timestamp with time zone");
DATA(insert OID = 1174 ( timestamptz PGNSP PGUID 12 f f t f s 1 1184 "1082" _null_ _null_ _null_ date_timestamptz - _null_ ));
DESCR("convert date to timestamp with time zone");
+DATA(insert OID = 2711 ( justify_interval PGNSP PGUID 12 f f t f i 1 1186 "1186" _null_ _null_ _null_ interval_justify_interval - _null_ ));
+DESCR("promote groups of 24 hours to numbers of days and promote groups of 30 days to numbers of months");
DATA(insert OID = 1175 ( justify_hours PGNSP PGUID 12 f f t f i 1 1186 "1186" _null_ _null_ _null_ interval_justify_hours - _null_ ));
DESCR("promote groups of 24 hours to numbers of days");
DATA(insert OID = 1295 ( justify_days PGNSP PGUID 12 f f t f i 1 1186 "1186" _null_ _null_ _null_ interval_justify_days - _null_ ));
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/utils/timestamp.h,v 1.58 2006/03/05 15:59:08 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/utils/timestamp.h,v 1.59 2006/03/06 22:49:17 momjian Exp $
*
*-------------------------------------------------------------------------
*/
extern Datum interval_hash(PG_FUNCTION_ARGS);
extern Datum interval_smaller(PG_FUNCTION_ARGS);
extern Datum interval_larger(PG_FUNCTION_ARGS);
+extern Datum interval_justify_interval(PG_FUNCTION_ARGS);
extern Datum interval_justify_hours(PG_FUNCTION_ARGS);
extern Datum interval_justify_days(PG_FUNCTION_ARGS);