]> granicus.if.org Git - postgresql/commitdiff
Implement "date/time grand unification".
authorThomas G. Lockhart <lockhart@fourpalms.org>
Wed, 16 Feb 2000 17:26:26 +0000 (17:26 +0000)
committerThomas G. Lockhart <lockhart@fourpalms.org>
Wed, 16 Feb 2000 17:26:26 +0000 (17:26 +0000)
 Transform datetime and timespan into timestamp and interval.
 Deprecate datetime and timespan, though translate to new types in gram.y.
 Transform all datetime and timespan catalog entries into new types.
 Make "INTERVAL" reserved word allowed as a column identifier in gram.y.
 Remove dt.h, dt.c files, and retarget datetime.h, datetime.c as utility
  routines for all date/time types.
 date.{h,c} now deals with date, time types.
 timestamp.{h,c} now deals with timestamp, interval types.
 nabstime.{h,c} now deals with abstime, reltime, tinterval types.
Make NUMERIC a known native type for purposes of type coersion. Not tested.

21 files changed:
src/backend/parser/gram.y
src/backend/parser/parse_coerce.c
src/backend/utils/adt/Makefile
src/backend/utils/adt/dt.c [deleted file]
src/backend/utils/adt/formatting.c
src/backend/utils/adt/nabstime.c
src/backend/utils/adt/timestamp.c
src/include/catalog/catversion.h
src/include/catalog/pg_aggregate.h
src/include/catalog/pg_opclass.h
src/include/catalog/pg_operator.h
src/include/catalog/pg_proc.h
src/include/catalog/pg_type.h
src/include/parser/parse_coerce.h
src/include/utils/builtins.h
src/include/utils/date.h [new file with mode: 0644]
src/include/utils/datetime.h
src/include/utils/dt.h [deleted file]
src/include/utils/formatting.h
src/include/utils/nabstime.h
src/include/utils/timestamp.h [new file with mode: 0644]

index 0da02fd8967a0511c9bfaca9cde09f7829cd9314..4babad9524a12b07ce8f1e3522162d15996b7f8d 100644 (file)
@@ -11,7 +11,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.142 2000/02/15 03:26:38 thomas Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.143 2000/02/16 17:24:36 thomas Exp $
  *
  * HISTORY
  *       AUTHOR                        DATE                    MAJOR EVENT
@@ -5180,6 +5180,7 @@ ColId:  IDENT                                                     { $$ = $1; }
                | INITIALLY                                             { $$ = "initially"; }
                | INSENSITIVE                                   { $$ = "insensitive"; }
                | INSTEAD                                               { $$ = "instead"; }
+               | INTERVAL                                              { $$ = "interval"; }
                | ISNULL                                                { $$ = "isnull"; }
                | ISOLATION                                             { $$ = "isolation"; }
                | KEY                                                   { $$ = "key"; }
@@ -5456,8 +5457,10 @@ xlateSqlType(char *name)
                return "numeric";
        else if (!strcasecmp(name, "char"))
                return "bpchar";
-       else if (!strcasecmp(name, "interval"))
-               return "timespan";
+       else if (!strcasecmp(name, "datetime"))
+               return "timestamp";
+       else if (!strcasecmp(name, "timespan"))
+               return "interval";
        else if (!strcasecmp(name, "boolean"))
                return "bool";
        else
index 67a34132388bf18df979b5ecb148ff7db5a302fd..7fa7b016881f9ec3fa13c696b2af411216805dac 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.29 2000/01/26 05:56:42 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.30 2000/02/16 17:24:37 thomas Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -293,18 +293,18 @@ TypeCategory(Oid inType)
                case (INT8OID):
                case (FLOAT4OID):
                case (FLOAT8OID):
+               case (NUMERICOID):
                case (CASHOID):
                        result = NUMERIC_TYPE;
                        break;
 
                case (ABSTIMEOID):
                case (TIMESTAMPOID):
-               case (DATETIMEOID):
                        result = DATETIME_TYPE;
                        break;
 
                case (RELTIMEOID):
-               case (TIMESPANOID):
+               case (INTERVALOID):
                        result = TIMESPAN_TYPE;
                        break;
 
@@ -362,16 +362,18 @@ PreferredType(CATEGORY category, Oid type)
                case (NUMERIC_TYPE):
                        if (type == OIDOID)
                                result = OIDOID;
+                       else if (type == NUMERICOID)
+                               result = NUMERICOID;
                        else
                                result = FLOAT8OID;
                        break;
 
                case (DATETIME_TYPE):
-                       result = DATETIMEOID;
+                       result = TIMESTAMPOID;
                        break;
 
                case (TIMESPAN_TYPE):
-                       result = TIMESPANOID;
+                       result = INTERVALOID;
                        break;
 
                case (NETWORK_TYPE):
@@ -419,22 +421,25 @@ PromoteTypeToNext(Oid inType)
                        result = FLOAT8OID;
                        break;
 
+               case (NUMERICOID):
+                       result = NUMERICOID;
+                       break;
+
                case (DATEOID):
                case (ABSTIMEOID):
-               case (TIMESTAMPOID):
-                       result = DATETIMEOID;
+                       result = TIMESTAMPOID;
                        break;
 
                case (TIMEOID):
                case (RELTIMEOID):
-                       result = TIMESPANOID;
+                       result = INTERVALOID;
                        break;
 
                case (BOOLOID):
                case (TEXTOID):
                case (FLOAT8OID):
-               case (DATETIMEOID):
-               case (TIMESPANOID):
+               case (TIMESTAMPOID):
+               case (INTERVALOID):
                default:
                        result = inType;
                        break;
index 192928db097d25d8907a23895c09f5df1661ef75..030ca951789e4e91841e961093fead8b338a0dfa 100644 (file)
@@ -4,7 +4,7 @@
 #    Makefile for utils/adt
 #
 # IDENTIFICATION
-#    $Header: /cvsroot/pgsql/src/backend/utils/adt/Makefile,v 1.33 2000/01/25 23:53:51 momjian Exp $
+#    $Header: /cvsroot/pgsql/src/backend/utils/adt/Makefile,v 1.34 2000/02/16 17:24:46 thomas Exp $
 #
 #-------------------------------------------------------------------------
 
@@ -24,7 +24,7 @@ endif
 endif
 
 OBJS = acl.o arrayfuncs.o arrayutils.o bool.o cash.o char.o chunk.o \
-       date.o datetime.o datum.o dt.o filename.o float.o \
+       date.o datetime.o datum.o filename.o float.o \
        geo_ops.o geo_selfuncs.o int.o int8.o like.o \
        misc.o nabstime.o name.o not_in.o numeric.o numutils.o \
        oid.o oracle_compat.o \
diff --git a/src/backend/utils/adt/dt.c b/src/backend/utils/adt/dt.c
deleted file mode 100644 (file)
index 90a5c5c..0000000
+++ /dev/null
@@ -1,4270 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * dt.c
- *       Functions for the built-in type "dt".
- *
- * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- *
- * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/dt.c,v 1.83 2000/02/15 03:17:09 thomas Exp $
- *
- *-------------------------------------------------------------------------
- */
-#include <ctype.h>
-#include <math.h>
-#include <sys/types.h>
-#include <errno.h>
-
-#include "postgres.h"
-#ifdef HAVE_FLOAT_H
-#include <float.h>
-#endif
-#ifdef HAVE_LIMITS_H
-#include <limits.h>
-#endif
-#ifndef USE_POSIX_TIME
-#include <sys/timeb.h>
-#endif
-
-#include "miscadmin.h"
-#include "utils/builtins.h"
-
-static int     DecodeDate(char *str, int fmask, int *tmask, struct tm * tm);
-static int DecodeNumber(int flen, char *field,
-       int fmask, int *tmask, struct tm * tm, double *fsec, int *is2digits);
-static int DecodeNumberField(int len, char *str,
-       int fmask, int *tmask, struct tm * tm, double *fsec, int *is2digits);
-static int     DecodeSpecial(int field, char *lowtoken, int *val);
-static int DecodeTime(char *str, int fmask, int *tmask,
-                  struct tm * tm, double *fsec);
-static int     DecodeTimezone(char *str, int *tzp);
-static int     DecodeUnits(int field, char *lowtoken, int *val);
-static int     EncodeSpecialDateTime(DateTime dt, char *str);
-static datetkn *datebsearch(char *key, datetkn *base, unsigned int nel);
-static DateTime dt2local(DateTime dt, int timezone);
-static void dt2time(DateTime dt, int *hour, int *min, double *sec);
-static int     j2day(int jd);
-static double time2t(const int hour, const int min, const double sec);
-static int     timespan2tm(TimeSpan span, struct tm * tm, float8 *fsec);
-static int     tm2timespan(struct tm * tm, double fsec, TimeSpan *span);
-
-
-#define USE_DATE_CACHE 1
-#define ROUND_ALL 0
-
-int                    day_tab[2][13] = {
-       {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 0},
-{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 0}};
-
-
-char      *months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
-"Jul", "Aug", "Sep", "Oct", "Nov", "Dec", NULL};
-
-char      *days[] = {"Sunday", "Monday", "Tuesday", "Wednesday",
-"Thursday", "Friday", "Saturday", NULL};
-
-/* TMODULO()
- * Macro to replace modf(), which is broken on some platforms.
- */
-#define TMODULO(t,q,u) \
-do { \
-       q = ((t < 0)? ceil(t / u): floor(t / u)); \
-       if (q != 0) \
-               t -= rint(q * u); \
-} while(0)
-
-static void GetEpochTime(struct tm * tm);
-
-#define UTIME_MINYEAR (1901)
-#define UTIME_MINMONTH (12)
-#define UTIME_MINDAY (14)
-#define UTIME_MAXYEAR (2038)
-#define UTIME_MAXMONTH (01)
-#define UTIME_MAXDAY (18)
-
-#define IS_VALID_UTIME(y,m,d) (((y > UTIME_MINYEAR) \
- || ((y == UTIME_MINYEAR) && ((m > UTIME_MINMONTH) \
-  || ((m == UTIME_MINMONTH) && (d >= UTIME_MINDAY))))) \
- && ((y < UTIME_MAXYEAR) \
- || ((y == UTIME_MAXYEAR) && ((m < UTIME_MAXMONTH) \
-  || ((m == UTIME_MAXMONTH) && (d <= UTIME_MAXDAY))))))
-
-
-/*****************************************************************************
- *      USER I/O ROUTINES                                                                                                               *
- *****************************************************************************/
-
-/* datetime_in()
- * Convert a string to internal form.
- */
-DateTime   *
-datetime_in(char *str)
-{
-       DateTime   *result;
-
-       double          fsec;
-       struct tm       tt,
-                          *tm = &tt;
-       int                     tz;
-       int                     dtype;
-       int                     nf;
-       char       *field[MAXDATEFIELDS];
-       int                     ftype[MAXDATEFIELDS];
-       char            lowstr[MAXDATELEN + 1];
-
-       if (!PointerIsValid(str))
-               elog(ERROR, "Bad (null) datetime external representation");
-
-       if ((ParseDateTime(str, lowstr, field, ftype, MAXDATEFIELDS, &nf) != 0)
-         || (DecodeDateTime(field, ftype, nf, &dtype, tm, &fsec, &tz) != 0))
-               elog(ERROR, "Bad datetime external representation '%s'", str);
-
-       result = palloc(sizeof(DateTime));
-
-       switch (dtype)
-       {
-               case DTK_DATE:
-                       if (tm2datetime(tm, fsec, &tz, result) != 0)
-                               elog(ERROR, "Datetime out of range '%s'", str);
-                       break;
-
-               case DTK_EPOCH:
-                       DATETIME_EPOCH(*result);
-                       break;
-
-               case DTK_CURRENT:
-                       DATETIME_CURRENT(*result);
-                       break;
-
-               case DTK_LATE:
-                       DATETIME_NOEND(*result);
-                       break;
-
-               case DTK_EARLY:
-                       DATETIME_NOBEGIN(*result);
-                       break;
-
-               case DTK_INVALID:
-                       DATETIME_INVALID(*result);
-                       break;
-
-               default:
-                       elog(ERROR, "Internal coding error, can't input datetime '%s'", str);
-       }
-
-       return result;
-}      /* datetime_in() */
-
-/* datetime_out()
- * Convert a datetime to external form.
- */
-char *
-datetime_out(DateTime *dt)
-{
-       char       *result;
-       int                     tz;
-       struct tm       tt,
-                          *tm = &tt;
-       double          fsec;
-       char       *tzn;
-       char            buf[MAXDATELEN + 1];
-
-       if (!PointerIsValid(dt))
-               return NULL;
-
-       if (DATETIME_IS_RESERVED(*dt))
-       {
-               EncodeSpecialDateTime(*dt, buf);
-
-       }
-       else if (datetime2tm(*dt, &tz, tm, &fsec, &tzn) == 0)
-       {
-               EncodeDateTime(tm, fsec, &tz, &tzn, DateStyle, buf);
-
-       }
-       else
-               EncodeSpecialDateTime(DT_INVALID, buf);
-
-       result = palloc(strlen(buf) + 1);
-
-       strcpy(result, buf);
-
-       return result;
-}      /* datetime_out() */
-
-
-/* timespan_in()
- * Convert a string to internal form.
- *
- * External format(s):
- *     Uses the generic date/time parsing and decoding routines.
- */
-TimeSpan   *
-timespan_in(char *str)
-{
-       TimeSpan   *span;
-
-       double          fsec;
-       struct tm       tt,
-                          *tm = &tt;
-       int                     dtype;
-       int                     nf;
-       char       *field[MAXDATEFIELDS];
-       int                     ftype[MAXDATEFIELDS];
-       char            lowstr[MAXDATELEN + 1];
-
-       tm->tm_year = 0;
-       tm->tm_mon = 0;
-       tm->tm_mday = 0;
-       tm->tm_hour = 0;
-       tm->tm_min = 0;
-       tm->tm_sec = 0;
-       fsec = 0;
-
-       if (!PointerIsValid(str))
-               elog(ERROR, "Bad (null) timespan external representation");
-
-       if ((ParseDateTime(str, lowstr, field, ftype, MAXDATEFIELDS, &nf) != 0)
-               || (DecodeDateDelta(field, ftype, nf, &dtype, tm, &fsec) != 0))
-               elog(ERROR, "Bad timespan external representation '%s'", str);
-
-       span = palloc(sizeof(TimeSpan));
-
-       switch (dtype)
-       {
-               case DTK_DELTA:
-                       if (tm2timespan(tm, fsec, span) != 0)
-                       {
-#if NOT_USED
-                               TIMESPAN_INVALID(span);
-#endif
-                               elog(ERROR, "Bad timespan external representation '%s'", str);
-                       }
-                       break;
-
-               default:
-                       elog(ERROR, "Internal coding error, can't input timespan '%s'", str);
-       }
-
-       return span;
-}      /* timespan_in() */
-
-/* timespan_out()
- * Convert a time span to external form.
- */
-char *
-timespan_out(TimeSpan *span)
-{
-       char       *result;
-
-       struct tm       tt,
-                          *tm = &tt;
-       double          fsec;
-       char            buf[MAXDATELEN + 1];
-
-       if (!PointerIsValid(span))
-               return NULL;
-
-       if (timespan2tm(*span, tm, &fsec) != 0)
-               return NULL;
-
-       if (EncodeTimeSpan(tm, fsec, DateStyle, buf) != 0)
-               elog(ERROR, "Unable to format timespan");
-
-       result = palloc(strlen(buf) + 1);
-
-       strcpy(result, buf);
-       return result;
-}      /* timespan_out() */
-
-
-/*****************************************************************************
- *      PUBLIC ROUTINES                                                                                                                 *
- *****************************************************************************/
-
-
-bool
-datetime_finite(DateTime *datetime)
-{
-       if (!PointerIsValid(datetime))
-               return FALSE;
-
-       return !DATETIME_NOT_FINITE(*datetime);
-}      /* datetime_finite() */
-
-bool
-timespan_finite(TimeSpan *timespan)
-{
-       if (!PointerIsValid(timespan))
-               return FALSE;
-
-       return !TIMESPAN_NOT_FINITE(*timespan);
-}      /* timespan_finite() */
-
-
-/*----------------------------------------------------------
- *     Relational operators for datetime.
- *---------------------------------------------------------*/
-
-static void
-GetEpochTime(struct tm * tm)
-{
-       struct tm  *t0;
-       time_t          epoch = 0;
-
-       t0 = gmtime(&epoch);
-
-       tm->tm_year = t0->tm_year;
-       tm->tm_mon = t0->tm_mon;
-       tm->tm_mday = t0->tm_mday;
-       tm->tm_hour = t0->tm_hour;
-       tm->tm_min = t0->tm_min;
-       tm->tm_sec = t0->tm_sec;
-
-       if (tm->tm_year < 1900)
-               tm->tm_year += 1900;
-       tm->tm_mon++;
-
-       return;
-}      /* GetEpochTime() */
-
-DateTime
-SetDateTime(DateTime dt)
-{
-       struct tm       tt;
-
-       if (DATETIME_IS_CURRENT(dt))
-       {
-               GetCurrentTime(&tt);
-               tm2datetime(&tt, 0, NULL, &dt);
-               dt = dt2local(dt, -CTimeZone);
-       }
-       else
-       {                                                       /* if (DATETIME_IS_EPOCH(dt1)) */
-               GetEpochTime(&tt);
-               tm2datetime(&tt, 0, NULL, &dt);
-       }
-
-       return dt;
-}      /* SetDateTime() */
-
-/*             datetime_relop  - is datetime1 relop datetime2
- */
-bool
-datetime_eq(DateTime *datetime1, DateTime *datetime2)
-{
-       DateTime        dt1,
-                               dt2;
-
-       if (!PointerIsValid(datetime1) || !PointerIsValid(datetime2))
-               return FALSE;
-
-       dt1 = *datetime1;
-       dt2 = *datetime2;
-
-       if (DATETIME_IS_INVALID(dt1) || DATETIME_IS_INVALID(dt2))
-               return FALSE;
-
-       if (DATETIME_IS_RELATIVE(dt1))
-               dt1 = SetDateTime(dt1);
-       if (DATETIME_IS_RELATIVE(dt2))
-               dt2 = SetDateTime(dt2);
-
-       return dt1 == dt2;
-}      /* datetime_eq() */
-
-bool
-datetime_ne(DateTime *datetime1, DateTime *datetime2)
-{
-       DateTime        dt1,
-                               dt2;
-
-       if (!PointerIsValid(datetime1) || !PointerIsValid(datetime2))
-               return FALSE;
-
-       dt1 = *datetime1;
-       dt2 = *datetime2;
-
-       if (DATETIME_IS_INVALID(dt1) || DATETIME_IS_INVALID(dt2))
-               return FALSE;
-
-       if (DATETIME_IS_RELATIVE(dt1))
-               dt1 = SetDateTime(dt1);
-       if (DATETIME_IS_RELATIVE(dt2))
-               dt2 = SetDateTime(dt2);
-
-       return dt1 != dt2;
-}      /* datetime_ne() */
-
-bool
-datetime_lt(DateTime *datetime1, DateTime *datetime2)
-{
-       DateTime        dt1,
-                               dt2;
-
-       if (!PointerIsValid(datetime1) || !PointerIsValid(datetime2))
-               return FALSE;
-
-       dt1 = *datetime1;
-       dt2 = *datetime2;
-
-       if (DATETIME_IS_INVALID(dt1) || DATETIME_IS_INVALID(dt2))
-               return FALSE;
-
-       if (DATETIME_IS_RELATIVE(dt1))
-               dt1 = SetDateTime(dt1);
-       if (DATETIME_IS_RELATIVE(dt2))
-               dt2 = SetDateTime(dt2);
-
-       return dt1 < dt2;
-}      /* datetime_lt() */
-
-bool
-datetime_gt(DateTime *datetime1, DateTime *datetime2)
-{
-       DateTime        dt1,
-                               dt2;
-
-       if (!PointerIsValid(datetime1) || !PointerIsValid(datetime2))
-               return FALSE;
-
-       dt1 = *datetime1;
-       dt2 = *datetime2;
-
-       if (DATETIME_IS_INVALID(dt1) || DATETIME_IS_INVALID(dt2))
-               return FALSE;
-
-       if (DATETIME_IS_RELATIVE(dt1))
-               dt1 = SetDateTime(dt1);
-       if (DATETIME_IS_RELATIVE(dt2))
-               dt2 = SetDateTime(dt2);
-
-       return dt1 > dt2;
-}      /* datetime_gt() */
-
-bool
-datetime_le(DateTime *datetime1, DateTime *datetime2)
-{
-       DateTime        dt1,
-                               dt2;
-
-       if (!PointerIsValid(datetime1) || !PointerIsValid(datetime2))
-               return FALSE;
-
-       dt1 = *datetime1;
-       dt2 = *datetime2;
-
-       if (DATETIME_IS_INVALID(dt1) || DATETIME_IS_INVALID(dt2))
-               return FALSE;
-
-       if (DATETIME_IS_RELATIVE(dt1))
-               dt1 = SetDateTime(dt1);
-       if (DATETIME_IS_RELATIVE(dt2))
-               dt2 = SetDateTime(dt2);
-
-       return dt1 <= dt2;
-}      /* datetime_le() */
-
-bool
-datetime_ge(DateTime *datetime1, DateTime *datetime2)
-{
-       DateTime        dt1,
-                               dt2;
-
-       if (!PointerIsValid(datetime1) || !PointerIsValid(datetime2))
-               return FALSE;
-
-       dt1 = *datetime1;
-       dt2 = *datetime2;
-
-       if (DATETIME_IS_INVALID(dt1) || DATETIME_IS_INVALID(dt2))
-               return FALSE;
-
-       if (DATETIME_IS_RELATIVE(dt1))
-               dt1 = SetDateTime(dt1);
-       if (DATETIME_IS_RELATIVE(dt2))
-               dt2 = SetDateTime(dt2);
-
-       return dt1 >= dt2;
-}      /* datetime_ge() */
-
-
-/*             datetime_cmp    - 3-state comparison for datetime
- *             collate invalid datetime at the end
- */
-int
-datetime_cmp(DateTime *datetime1, DateTime *datetime2)
-{
-       DateTime        dt1,
-                               dt2;
-
-       if (!PointerIsValid(datetime1) || !PointerIsValid(datetime2))
-               return 0;
-
-       dt1 = *datetime1;
-       dt2 = *datetime2;
-
-       if (DATETIME_IS_INVALID(dt1))
-       {
-               return (DATETIME_IS_INVALID(dt2) ? 0 : 1);
-
-       }
-       else if (DATETIME_IS_INVALID(dt2))
-       {
-               return -1;
-
-       }
-       else
-       {
-               if (DATETIME_IS_RELATIVE(dt1))
-                       dt1 = SetDateTime(dt1);
-               if (DATETIME_IS_RELATIVE(dt2))
-                       dt2 = SetDateTime(dt2);
-       }
-
-       return ((dt1 < dt2) ? -1 : ((dt1 > dt2) ? 1 : 0));
-}      /* datetime_cmp() */
-
-
-/*             timespan_relop  - is timespan1 relop timespan2
- */
-bool
-timespan_eq(TimeSpan *timespan1, TimeSpan *timespan2)
-{
-       if (!PointerIsValid(timespan1) || !PointerIsValid(timespan2))
-               return FALSE;
-
-       if (TIMESPAN_IS_INVALID(*timespan1) || TIMESPAN_IS_INVALID(*timespan2))
-               return FALSE;
-
-       return ((timespan1->time == timespan2->time)
-                       && (timespan1->month == timespan2->month));
-}      /* timespan_eq() */
-
-bool
-timespan_ne(TimeSpan *timespan1, TimeSpan *timespan2)
-{
-       if (!PointerIsValid(timespan1) || !PointerIsValid(timespan2))
-               return FALSE;
-
-       if (TIMESPAN_IS_INVALID(*timespan1) || TIMESPAN_IS_INVALID(*timespan2))
-               return FALSE;
-
-       return ((timespan1->time != timespan2->time)
-                       || (timespan1->month != timespan2->month));
-}      /* timespan_ne() */
-
-bool
-timespan_lt(TimeSpan *timespan1, TimeSpan *timespan2)
-{
-       double          span1,
-                               span2;
-
-       if (!PointerIsValid(timespan1) || !PointerIsValid(timespan2))
-               return FALSE;
-
-       if (TIMESPAN_IS_INVALID(*timespan1) || TIMESPAN_IS_INVALID(*timespan2))
-               return FALSE;
-
-       span1 = timespan1->time;
-       if (timespan1->month != 0)
-               span1 += (timespan1->month * (30.0 * 86400));
-       span2 = timespan2->time;
-       if (timespan2->month != 0)
-               span2 += (timespan2->month * (30.0 * 86400));
-
-       return span1 < span2;
-}      /* timespan_lt() */
-
-bool
-timespan_gt(TimeSpan *timespan1, TimeSpan *timespan2)
-{
-       double          span1,
-                               span2;
-
-       if (!PointerIsValid(timespan1) || !PointerIsValid(timespan2))
-               return FALSE;
-
-       if (TIMESPAN_IS_INVALID(*timespan1) || TIMESPAN_IS_INVALID(*timespan2))
-               return FALSE;
-
-       span1 = timespan1->time;
-       if (timespan1->month != 0)
-               span1 += (timespan1->month * (30.0 * 86400));
-       span2 = timespan2->time;
-       if (timespan2->month != 0)
-               span2 += (timespan2->month * (30.0 * 86400));
-
-       return span1 > span2;
-}      /* timespan_gt() */
-
-bool
-timespan_le(TimeSpan *timespan1, TimeSpan *timespan2)
-{
-       double          span1,
-                               span2;
-
-       if (!PointerIsValid(timespan1) || !PointerIsValid(timespan2))
-               return FALSE;
-
-       if (TIMESPAN_IS_INVALID(*timespan1) || TIMESPAN_IS_INVALID(*timespan2))
-               return FALSE;
-
-       span1 = timespan1->time;
-       if (timespan1->month != 0)
-               span1 += (timespan1->month * (30.0 * 86400));
-       span2 = timespan2->time;
-       if (timespan2->month != 0)
-               span2 += (timespan2->month * (30.0 * 86400));
-
-       return span1 <= span2;
-}      /* timespan_le() */
-
-bool
-timespan_ge(TimeSpan *timespan1, TimeSpan *timespan2)
-{
-       double          span1,
-                               span2;
-
-       if (!PointerIsValid(timespan1) || !PointerIsValid(timespan2))
-               return FALSE;
-
-       if (TIMESPAN_IS_INVALID(*timespan1) || TIMESPAN_IS_INVALID(*timespan2))
-               return FALSE;
-
-       span1 = timespan1->time;
-       if (timespan1->month != 0)
-               span1 += (timespan1->month * (30.0 * 86400));
-       span2 = timespan2->time;
-       if (timespan2->month != 0)
-               span2 += (timespan2->month * (30.0 * 86400));
-
-       return span1 >= span2;
-}      /* timespan_ge() */
-
-
-/*             timespan_cmp    - 3-state comparison for timespan
- */
-int
-timespan_cmp(TimeSpan *timespan1, TimeSpan *timespan2)
-{
-       double          span1,
-                               span2;
-
-       if (!PointerIsValid(timespan1) || !PointerIsValid(timespan2))
-               return 0;
-
-       if (TIMESPAN_IS_INVALID(*timespan1))
-       {
-               return TIMESPAN_IS_INVALID(*timespan2) ? 0 : 1;
-
-       }
-       else if (TIMESPAN_IS_INVALID(*timespan2))
-               return -1;
-
-       span1 = timespan1->time;
-       if (timespan1->month != 0)
-               span1 += (timespan1->month * (30.0 * 86400));
-       span2 = timespan2->time;
-       if (timespan2->month != 0)
-               span2 += (timespan2->month * (30.0 * 86400));
-
-       return (span1 < span2) ? -1 : (span1 > span2) ? 1 : 0;
-}      /* timespan_cmp() */
-
-
-/*----------------------------------------------------------
- *     "Arithmetic" operators on date/times.
- *             datetime_foo    returns foo as an object (pointer) that
- *                                             can be passed between languages.
- *             datetime_xx             is an internal routine which returns the
- *                                             actual value.
- *---------------------------------------------------------*/
-
-DateTime   *
-datetime_smaller(DateTime *datetime1, DateTime *datetime2)
-{
-       DateTime   *result;
-
-       DateTime        dt1,
-                               dt2;
-
-       if (!PointerIsValid(datetime1) || !PointerIsValid(datetime2))
-               return NULL;
-
-       dt1 = *datetime1;
-       dt2 = *datetime2;
-
-       result = palloc(sizeof(DateTime));
-
-       if (DATETIME_IS_RELATIVE(dt1))
-               dt1 = SetDateTime(dt1);
-       if (DATETIME_IS_RELATIVE(dt2))
-               dt2 = SetDateTime(dt2);
-
-       if (DATETIME_IS_INVALID(dt1))
-               *result = dt2;
-       else if (DATETIME_IS_INVALID(dt2))
-               *result = dt1;
-       else
-               *result = ((dt2 < dt1) ? dt2 : dt1);
-
-       return result;
-}      /* datetime_smaller() */
-
-DateTime   *
-datetime_larger(DateTime *datetime1, DateTime *datetime2)
-{
-       DateTime   *result;
-
-       DateTime        dt1,
-                               dt2;
-
-       if (!PointerIsValid(datetime1) || !PointerIsValid(datetime2))
-               return NULL;
-
-       dt1 = *datetime1;
-       dt2 = *datetime2;
-
-       result = palloc(sizeof(DateTime));
-
-       if (DATETIME_IS_RELATIVE(dt1))
-               dt1 = SetDateTime(dt1);
-       if (DATETIME_IS_RELATIVE(dt2))
-               dt2 = SetDateTime(dt2);
-
-       if (DATETIME_IS_INVALID(dt1))
-               *result = dt2;
-       else if (DATETIME_IS_INVALID(dt2))
-               *result = dt1;
-       else
-               *result = ((dt2 > dt1) ? dt2 : dt1);
-
-       return result;
-}      /* datetime_larger() */
-
-
-TimeSpan   *
-datetime_mi(DateTime *datetime1, DateTime *datetime2)
-{
-       TimeSpan   *result;
-
-       DateTime        dt1,
-                               dt2;
-
-       if (!PointerIsValid(datetime1) || !PointerIsValid(datetime2))
-               return NULL;
-
-       dt1 = *datetime1;
-       dt2 = *datetime2;
-
-       result = palloc(sizeof(TimeSpan));
-
-       if (DATETIME_IS_RELATIVE(dt1))
-               dt1 = SetDateTime(dt1);
-       if (DATETIME_IS_RELATIVE(dt2))
-               dt2 = SetDateTime(dt2);
-
-       if (DATETIME_IS_INVALID(dt1)
-               || DATETIME_IS_INVALID(dt2))
-       {
-               DATETIME_INVALID(result->time);
-
-       }
-       else
-               result->time = JROUND(dt1 - dt2);
-       result->month = 0;
-
-       return result;
-}      /* datetime_mi() */
-
-
-/* datetime_pl_span()
- * Add a timespan to a datetime data type.
- * Note that timespan has provisions for qualitative year/month
- *     units, so try to do the right thing with them.
- * To add a month, increment the month, and use the same day of month.
- * Then, if the next month has fewer days, set the day of month
- *     to the last day of month.
- * Lastly, add in the "quantitative time".
- */
-DateTime   *
-datetime_pl_span(DateTime *datetime, TimeSpan *span)
-{
-       DateTime   *result;
-       DateTime        dt;
-       int                     tz;
-       char       *tzn;
-
-       if ((!PointerIsValid(datetime)) || (!PointerIsValid(span)))
-               return NULL;
-
-       result = palloc(sizeof(DateTime));
-
-       if (DATETIME_NOT_FINITE(*datetime))
-       {
-               *result = *datetime;
-
-       }
-       else if (TIMESPAN_IS_INVALID(*span))
-       {
-               DATETIME_INVALID(*result);
-
-       }
-       else
-       {
-               dt = (DATETIME_IS_RELATIVE(*datetime) ? SetDateTime(*datetime) : *datetime);
-
-               if (span->month != 0)
-               {
-                       struct tm       tt,
-                                          *tm = &tt;
-                       double          fsec;
-
-                       if (datetime2tm(dt, &tz, tm, &fsec, &tzn) == 0)
-                       {
-                               tm->tm_mon += span->month;
-                               if (tm->tm_mon > 12)
-                               {
-                                       tm->tm_year += ((tm->tm_mon - 1) / 12);
-                                       tm->tm_mon = (((tm->tm_mon - 1) % 12) + 1);
-                               }
-                               else if (tm->tm_mon < 1)
-                               {
-                                       tm->tm_year += ((tm->tm_mon / 12) - 1);
-                                       tm->tm_mon = ((tm->tm_mon % 12) + 12);
-                               }
-
-                               /* adjust for end of month boundary problems... */
-                               if (tm->tm_mday > day_tab[isleap(tm->tm_year)][tm->tm_mon - 1])
-                                       tm->tm_mday = (day_tab[isleap(tm->tm_year)][tm->tm_mon - 1]);
-
-                               if (tm2datetime(tm, fsec, &tz, &dt) != 0)
-                                       elog(ERROR, "Unable to add datetime and timespan");
-
-                       }
-                       else
-                               DATETIME_INVALID(dt);
-               }
-
-#ifdef ROUND_ALL
-               dt = JROUND(dt + span->time);
-#else
-               dt += span->time;
-#endif
-
-               *result = dt;
-       }
-
-       return result;
-}      /* datetime_pl_span() */
-
-DateTime   *
-datetime_mi_span(DateTime *datetime, TimeSpan *span)
-{
-       DateTime   *result;
-       TimeSpan        tspan;
-
-       if (!PointerIsValid(datetime) || !PointerIsValid(span))
-               return NULL;
-
-       tspan.month = -span->month;
-       tspan.time = -span->time;
-
-       result = datetime_pl_span(datetime, &tspan);
-
-       return result;
-}      /* datetime_mi_span() */
-
-
-TimeSpan   *
-timespan_um(TimeSpan *timespan)
-{
-       TimeSpan   *result;
-
-       if (!PointerIsValid(timespan))
-               return NULL;
-
-       result = palloc(sizeof(TimeSpan));
-
-       result->time = -(timespan->time);
-       result->month = -(timespan->month);
-
-       return result;
-}      /* timespan_um() */
-
-
-TimeSpan   *
-timespan_smaller(TimeSpan *timespan1, TimeSpan *timespan2)
-{
-       TimeSpan   *result;
-
-       double          span1,
-                               span2;
-
-       if (!PointerIsValid(timespan1) || !PointerIsValid(timespan2))
-               return NULL;
-
-       result = palloc(sizeof(TimeSpan));
-
-       if (TIMESPAN_IS_INVALID(*timespan1))
-       {
-               result->time = timespan2->time;
-               result->month = timespan2->month;
-
-       }
-       else if (TIMESPAN_IS_INVALID(*timespan2))
-       {
-               result->time = timespan1->time;
-               result->month = timespan1->month;
-
-       }
-       else
-       {
-               span1 = timespan1->time;
-               if (timespan1->month != 0)
-                       span1 += (timespan1->month * (30.0 * 86400));
-               span2 = timespan2->time;
-               if (timespan2->month != 0)
-                       span2 += (timespan2->month * (30.0 * 86400));
-
-               if (span2 < span1)
-               {
-                       result->time = timespan2->time;
-                       result->month = timespan2->month;
-
-               }
-               else
-               {
-                       result->time = timespan1->time;
-                       result->month = timespan1->month;
-               }
-       }
-
-       return result;
-}      /* timespan_smaller() */
-
-TimeSpan   *
-timespan_larger(TimeSpan *timespan1, TimeSpan *timespan2)
-{
-       TimeSpan   *result;
-
-       double          span1,
-                               span2;
-
-       if (!PointerIsValid(timespan1) || !PointerIsValid(timespan2))
-               return NULL;
-
-       result = palloc(sizeof(TimeSpan));
-
-       if (TIMESPAN_IS_INVALID(*timespan1))
-       {
-               result->time = timespan2->time;
-               result->month = timespan2->month;
-
-       }
-       else if (TIMESPAN_IS_INVALID(*timespan2))
-       {
-               result->time = timespan1->time;
-               result->month = timespan1->month;
-
-       }
-       else
-       {
-               span1 = timespan1->time;
-               if (timespan1->month != 0)
-                       span1 += (timespan1->month * (30.0 * 86400));
-               span2 = timespan2->time;
-               if (timespan2->month != 0)
-                       span2 += (timespan2->month * (30.0 * 86400));
-
-               if (span2 > span1)
-               {
-                       result->time = timespan2->time;
-                       result->month = timespan2->month;
-
-               }
-               else
-               {
-                       result->time = timespan1->time;
-                       result->month = timespan1->month;
-               }
-       }
-
-       return result;
-}      /* timespan_larger() */
-
-
-TimeSpan   *
-timespan_pl(TimeSpan *span1, TimeSpan *span2)
-{
-       TimeSpan   *result;
-
-       if ((!PointerIsValid(span1)) || (!PointerIsValid(span2)))
-               return NULL;
-
-       result = palloc(sizeof(TimeSpan));
-
-       result->month = (span1->month + span2->month);
-       result->time = JROUND(span1->time + span2->time);
-
-       return result;
-}      /* timespan_pl() */
-
-TimeSpan   *
-timespan_mi(TimeSpan *span1, TimeSpan *span2)
-{
-       TimeSpan   *result;
-
-       if ((!PointerIsValid(span1)) || (!PointerIsValid(span2)))
-               return NULL;
-
-       result = palloc(sizeof(TimeSpan));
-
-       result->month = (span1->month - span2->month);
-       result->time = JROUND(span1->time - span2->time);
-
-       return result;
-}      /* timespan_mi() */
-
-TimeSpan   *
-timespan_div(TimeSpan *span1, float8 *arg2)
-{
-       TimeSpan   *result;
-
-       if ((!PointerIsValid(span1)) || (!PointerIsValid(arg2)))
-               return NULL;
-
-       if (!PointerIsValid(result = palloc(sizeof(TimeSpan))))
-               elog(ERROR, "Memory allocation failed, can't divide timespans");
-
-       if (*arg2 == 0.0)
-               elog(ERROR, "timespan_div:  divide by 0.0 error");
-
-       result->month = rint(span1->month / *arg2);
-       result->time = JROUND(span1->time / *arg2);
-
-       return result;
-}      /* timespan_div() */
-
-/* datetime_age()
- * Calculate time difference while retaining year/month fields.
- * Note that this does not result in an accurate absolute time span
- *     since year and month are out of context once the arithmetic
- *     is done.
- */
-TimeSpan   *
-datetime_age(DateTime *datetime1, DateTime *datetime2)
-{
-       TimeSpan   *result;
-
-       DateTime        dt1,
-                               dt2;
-       double          fsec,
-                               fsec1,
-                               fsec2;
-       struct tm       tt,
-                          *tm = &tt;
-       struct tm       tt1,
-                          *tm1 = &tt1;
-       struct tm       tt2,
-                          *tm2 = &tt2;
-
-       if (!PointerIsValid(datetime1) || !PointerIsValid(datetime2))
-               return NULL;
-
-       result = palloc(sizeof(TimeSpan));
-
-       dt1 = *datetime1;
-       dt2 = *datetime2;
-
-       if (DATETIME_IS_RELATIVE(dt1))
-               dt1 = SetDateTime(dt1);
-       if (DATETIME_IS_RELATIVE(dt2))
-               dt2 = SetDateTime(dt2);
-
-       if (DATETIME_IS_INVALID(dt1)
-               || DATETIME_IS_INVALID(dt2))
-       {
-               DATETIME_INVALID(result->time);
-
-       }
-       else if ((datetime2tm(dt1, NULL, tm1, &fsec1, NULL) == 0)
-                        && (datetime2tm(dt2, NULL, tm2, &fsec2, 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);
-               tm->tm_mday = (tm1->tm_mday - tm2->tm_mday);
-               tm->tm_mon = (tm1->tm_mon - tm2->tm_mon);
-               tm->tm_year = (tm1->tm_year - tm2->tm_year);
-
-               /* flip sign if necessary... */
-               if (dt1 < dt2)
-               {
-                       fsec = -fsec;
-                       tm->tm_sec = -tm->tm_sec;
-                       tm->tm_min = -tm->tm_min;
-                       tm->tm_hour = -tm->tm_hour;
-                       tm->tm_mday = -tm->tm_mday;
-                       tm->tm_mon = -tm->tm_mon;
-                       tm->tm_year = -tm->tm_year;
-               }
-
-               if (tm->tm_sec < 0)
-               {
-                       tm->tm_sec += 60;
-                       tm->tm_min--;
-               }
-
-               if (tm->tm_min < 0)
-               {
-                       tm->tm_min += 60;
-                       tm->tm_hour--;
-               }
-
-               if (tm->tm_hour < 0)
-               {
-                       tm->tm_hour += 24;
-                       tm->tm_mday--;
-               }
-
-               if (tm->tm_mday < 0)
-               {
-                       if (dt1 < dt2)
-                       {
-                               tm->tm_mday += day_tab[isleap(tm1->tm_year)][tm1->tm_mon - 1];
-                               tm->tm_mon--;
-                       }
-                       else
-                       {
-                               tm->tm_mday += day_tab[isleap(tm2->tm_year)][tm2->tm_mon - 1];
-                               tm->tm_mon--;
-                       }
-               }
-
-               if (tm->tm_mon < 0)
-               {
-                       tm->tm_mon += 12;
-                       tm->tm_year--;
-               }
-
-               /* recover sign if necessary... */
-               if (dt1 < dt2)
-               {
-                       fsec = -fsec;
-                       tm->tm_sec = -tm->tm_sec;
-                       tm->tm_min = -tm->tm_min;
-                       tm->tm_hour = -tm->tm_hour;
-                       tm->tm_mday = -tm->tm_mday;
-                       tm->tm_mon = -tm->tm_mon;
-                       tm->tm_year = -tm->tm_year;
-               }
-
-               if (tm2timespan(tm, fsec, result) != 0)
-                       elog(ERROR, "Unable to decode datetime");
-
-       }
-       else
-               elog(ERROR, "Unable to decode datetime");
-
-       return result;
-}      /* datetime_age() */
-
-
-/*----------------------------------------------------------
- *     Conversion operators.
- *---------------------------------------------------------*/
-
-
-/* datetime_text()
- * Convert datetime to text data type.
- */
-text *
-datetime_text(DateTime *datetime)
-{
-       text       *result;
-       char       *str;
-       int                     len;
-
-       if (!PointerIsValid(datetime))
-               return NULL;
-
-       str = datetime_out(datetime);
-
-       if (!PointerIsValid(str))
-               return NULL;
-
-       len = (strlen(str) + VARHDRSZ);
-
-       result = palloc(len);
-
-       VARSIZE(result) = len;
-       memmove(VARDATA(result), str, (len - VARHDRSZ));
-
-       pfree(str);
-
-       return result;
-}      /* datetime_text() */
-
-
-/* text_datetime()
- * Convert text string to datetime.
- * Text type is not null terminated, so use temporary string
- *     then call the standard input routine.
- */
-DateTime   *
-text_datetime(text *str)
-{
-       DateTime   *result;
-       int                     i;
-       char       *sp,
-                          *dp,
-                               dstr[MAXDATELEN + 1];
-
-       if (!PointerIsValid(str))
-               return NULL;
-
-       sp = VARDATA(str);
-       dp = dstr;
-       for (i = 0; i < (VARSIZE(str) - VARHDRSZ); i++)
-               *dp++ = *sp++;
-       *dp = '\0';
-
-       result = datetime_in(dstr);
-
-       return result;
-}      /* text_datetime() */
-
-
-/* timespan_text()
- * Convert timespan to text data type.
- */
-text *
-timespan_text(TimeSpan *timespan)
-{
-       text       *result;
-       char       *str;
-       int                     len;
-
-       if (!PointerIsValid(timespan))
-               return NULL;
-
-       str = timespan_out(timespan);
-
-       if (!PointerIsValid(str))
-               return NULL;
-
-       len = (strlen(str) + VARHDRSZ);
-
-       result = palloc(len);
-
-       VARSIZE(result) = len;
-       memmove(VARDATA(result), str, (len - VARHDRSZ));
-
-       pfree(str);
-
-       return result;
-}      /* timespan_text() */
-
-
-/* text_timespan()
- * Convert text string to timespan.
- * Text type may not be null terminated, so copy to temporary string
- *     then call the standard input routine.
- */
-TimeSpan   *
-text_timespan(text *str)
-{
-       TimeSpan   *result;
-       int                     i;
-       char       *sp,
-                          *dp,
-                               dstr[MAXDATELEN + 1];
-
-       if (!PointerIsValid(str))
-               return NULL;
-
-       sp = VARDATA(str);
-       dp = dstr;
-       for (i = 0; i < (VARSIZE(str) - VARHDRSZ); i++)
-               *dp++ = *sp++;
-       *dp = '\0';
-
-       result = timespan_in(dstr);
-
-       return result;
-}      /* text_timespan() */
-
-/* datetime_trunc()
- * Extract specified field from datetime.
- */
-DateTime   *
-datetime_trunc(text *units, DateTime *datetime)
-{
-       DateTime   *result;
-
-       DateTime        dt;
-       int                     tz;
-       int                     type,
-                               val;
-       int                     i;
-       char       *up,
-                          *lp,
-                               lowunits[MAXDATELEN + 1];
-       double          fsec;
-       char       *tzn;
-       struct tm       tt,
-                          *tm = &tt;
-
-       if ((!PointerIsValid(units)) || (!PointerIsValid(datetime)))
-               return NULL;
-
-       result = palloc(sizeof(DateTime));
-
-       up = VARDATA(units);
-       lp = lowunits;
-       for (i = 0; i < (VARSIZE(units) - VARHDRSZ); i++)
-               *lp++ = tolower(*up++);
-       *lp = '\0';
-
-       type = DecodeUnits(0, lowunits, &val);
-
-       if (DATETIME_NOT_FINITE(*datetime))
-       {
-#if NOT_USED
-/* should return null but Postgres doesn't like that currently. - tgl 97/06/12 */
-               elog(ERROR, "Datetime is not finite", NULL);
-#endif
-               *result = 0;
-
-       }
-       else
-       {
-               dt = (DATETIME_IS_RELATIVE(*datetime) ? SetDateTime(*datetime) : *datetime);
-
-               if ((type == UNITS) && (datetime2tm(dt, &tz, tm, &fsec, &tzn) == 0))
-               {
-                       switch (val)
-                       {
-                               case DTK_MILLENIUM:
-                                       tm->tm_year = (tm->tm_year / 1000) * 1000;
-                               case DTK_CENTURY:
-                                       tm->tm_year = (tm->tm_year / 100) * 100;
-                               case DTK_DECADE:
-                                       tm->tm_year = (tm->tm_year / 10) * 10;
-                               case DTK_YEAR:
-                                       tm->tm_mon = 1;
-                               case DTK_QUARTER:
-                                       tm->tm_mon = (3 * (tm->tm_mon / 4)) + 1;
-                               case DTK_MONTH:
-                                       tm->tm_mday = 1;
-                               case DTK_DAY:
-                                       tm->tm_hour = 0;
-                               case DTK_HOUR:
-                                       tm->tm_min = 0;
-                               case DTK_MINUTE:
-                                       tm->tm_sec = 0;
-                               case DTK_SECOND:
-                                       fsec = 0;
-                                       break;
-
-                               case DTK_MILLISEC:
-                                       fsec = rint(fsec * 1000) / 1000;
-                                       break;
-
-                               case DTK_MICROSEC:
-                                       fsec = rint(fsec * 1000000) / 1000000;
-                                       break;
-
-                               default:
-                                       elog(ERROR, "Datetime units '%s' not supported", lowunits);
-                                       result = NULL;
-                       }
-
-                       if (IS_VALID_UTIME(tm->tm_year, tm->tm_mon, tm->tm_mday))
-                       {
-#ifdef USE_POSIX_TIME
-                               tm->tm_isdst = -1;
-                               tm->tm_year -= 1900;
-                               tm->tm_mon -= 1;
-                               tm->tm_isdst = -1;
-                               mktime(tm);
-                               tm->tm_year += 1900;
-                               tm->tm_mon += 1;
-
-#if defined(HAVE_TM_ZONE)
-                               tz = -(tm->tm_gmtoff);  /* tm_gmtoff is Sun/DEC-ism */
-#elif defined(HAVE_INT_TIMEZONE)
-
-#ifdef __CYGWIN__
-                               tz = (tm->tm_isdst ? (_timezone - 3600) : _timezone);
-#else
-                               tz = (tm->tm_isdst ? (timezone - 3600) : timezone);
-#endif
-
-#else
-#error USE_POSIX_TIME is defined but neither HAVE_TM_ZONE or HAVE_INT_TIMEZONE are defined
-#endif
-
-#else                                                  /* !USE_POSIX_TIME */
-                               tz = CTimeZone;
-#endif
-                       }
-                       else
-                       {
-                               tm->tm_isdst = 0;
-                               tz = 0;
-                       }
-
-                       if (tm2datetime(tm, fsec, &tz, result) != 0)
-                               elog(ERROR, "Unable to truncate datetime to '%s'", lowunits);
-
-#if NOT_USED
-               }
-               else if ((type == RESERV) && (val == DTK_EPOCH))
-               {
-                       DATETIME_EPOCH(*result);
-                       *result = dt - SetDateTime(*result);
-#endif
-
-               }
-               else
-               {
-                       elog(ERROR, "Datetime units '%s' not recognized", lowunits);
-                       result = NULL;
-               }
-       }
-
-       return result;
-}      /* datetime_trunc() */
-
-/* timespan_trunc()
- * Extract specified field from timespan.
- */
-TimeSpan   *
-timespan_trunc(text *units, TimeSpan *timespan)
-{
-       TimeSpan   *result;
-
-       int                     type,
-                               val;
-       int                     i;
-       char       *up,
-                          *lp,
-                               lowunits[MAXDATELEN + 1];
-       double          fsec;
-       struct tm       tt,
-                          *tm = &tt;
-
-       if ((!PointerIsValid(units)) || (!PointerIsValid(timespan)))
-               return NULL;
-
-       result = palloc(sizeof(TimeSpan));
-
-       up = VARDATA(units);
-       lp = lowunits;
-       for (i = 0; i < (VARSIZE(units) - VARHDRSZ); i++)
-               *lp++ = tolower(*up++);
-       *lp = '\0';
-
-       type = DecodeUnits(0, lowunits, &val);
-
-       if (TIMESPAN_IS_INVALID(*timespan))
-       {
-#if NOT_USED
-               elog(ERROR, "Timespan is not finite", NULL);
-#endif
-               result = NULL;
-
-       }
-       else if (type == UNITS)
-       {
-
-               if (timespan2tm(*timespan, tm, &fsec) == 0)
-               {
-                       switch (val)
-                       {
-                               case DTK_MILLENIUM:
-                                       tm->tm_year = (tm->tm_year / 1000) * 1000;
-                               case DTK_CENTURY:
-                                       tm->tm_year = (tm->tm_year / 100) * 100;
-                               case DTK_DECADE:
-                                       tm->tm_year = (tm->tm_year / 10) * 10;
-                               case DTK_YEAR:
-                                       tm->tm_mon = 0;
-                               case DTK_QUARTER:
-                                       tm->tm_mon = (3 * (tm->tm_mon / 4));
-                               case DTK_MONTH:
-                                       tm->tm_mday = 0;
-                               case DTK_DAY:
-                                       tm->tm_hour = 0;
-                               case DTK_HOUR:
-                                       tm->tm_min = 0;
-                               case DTK_MINUTE:
-                                       tm->tm_sec = 0;
-                               case DTK_SECOND:
-                                       fsec = 0;
-                                       break;
-
-                               case DTK_MILLISEC:
-                                       fsec = rint(fsec * 1000) / 1000;
-                                       break;
-
-                               case DTK_MICROSEC:
-                                       fsec = rint(fsec * 1000000) / 1000000;
-                                       break;
-
-                               default:
-                                       elog(ERROR, "Timespan units '%s' not supported", lowunits);
-                                       result = NULL;
-                       }
-
-                       if (tm2timespan(tm, fsec, result) != 0)
-                               elog(ERROR, "Unable to truncate timespan to '%s'", lowunits);
-
-               }
-               else
-               {
-                       elog(NOTICE, "Timespan out of range");
-                       result = NULL;
-               }
-
-#if NOT_USED
-       }
-       else if ((type == RESERV) && (val == DTK_EPOCH))
-       {
-               *result = timespan->time;
-               if (timespan->month != 0)
-               {
-                       *result += ((365.25 * 86400) * (timespan->month / 12));
-                       *result += ((30 * 86400) * (timespan->month % 12));
-               }
-#endif
-
-       }
-       else
-       {
-               elog(ERROR, "Timespan units '%s' not recognized", textout(units));
-               result = NULL;
-       }
-
-       return result;
-}      /* timespan_trunc() */
-
-
-/* datetime_part()
- * Extract specified field from datetime.
- */
-float64
-datetime_part(text *units, DateTime *datetime)
-{
-       float64         result;
-
-       DateTime        dt;
-       int                     tz;
-       int                     type,
-                               val;
-       int                     i;
-       char       *up,
-                          *lp,
-                               lowunits[MAXDATELEN + 1];
-       double          dummy;
-       double          fsec;
-       char       *tzn;
-       struct tm       tt,
-                          *tm = &tt;
-
-       if ((!PointerIsValid(units)) || (!PointerIsValid(datetime)))
-               return NULL;
-
-       result = palloc(sizeof(float64data));
-
-       up = VARDATA(units);
-       lp = lowunits;
-       for (i = 0; i < (VARSIZE(units) - VARHDRSZ); i++)
-               *lp++ = tolower(*up++);
-       *lp = '\0';
-
-       type = DecodeUnits(0, lowunits, &val);
-       if (type == IGNORE)
-               type = DecodeSpecial(0, lowunits, &val);
-
-       if (DATETIME_NOT_FINITE(*datetime))
-       {
-#if NOT_USED
-/* should return null but Postgres doesn't like that currently. - tgl 97/06/12 */
-               elog(ERROR, "Datetime is not finite", NULL);
-#endif
-               *result = 0;
-
-       }
-       else
-       {
-               dt = (DATETIME_IS_RELATIVE(*datetime) ? SetDateTime(*datetime) : *datetime);
-
-               if ((type == UNITS) && (datetime2tm(dt, &tz, tm, &fsec, &tzn) == 0))
-               {
-                       switch (val)
-                       {
-                               case DTK_TZ:
-                                       *result = tz;
-                                       break;
-
-                               case DTK_TZ_MINUTE:
-                                       *result = tz / 60;
-                                       TMODULO(*result, dummy, 60e0);
-                                       break;
-
-                               case DTK_TZ_HOUR:
-                                       dummy = tz;
-                                       TMODULO(dummy, *result, 3600e0);
-                                       break;
-
-                               case DTK_MICROSEC:
-                                       *result = (fsec * 1000000);
-                                       break;
-
-                               case DTK_MILLISEC:
-                                       *result = (fsec * 1000);
-                                       break;
-
-                               case DTK_SECOND:
-                                       *result = (tm->tm_sec + fsec);
-                                       break;
-
-                               case DTK_MINUTE:
-                                       *result = tm->tm_min;
-                                       break;
-
-                               case DTK_HOUR:
-                                       *result = tm->tm_hour;
-                                       break;
-
-                               case DTK_DAY:
-                                       *result = tm->tm_mday;
-                                       break;
-
-                               case DTK_MONTH:
-                                       *result = tm->tm_mon;
-                                       break;
-
-                               case DTK_QUARTER:
-                                       *result = (tm->tm_mon / 4) + 1;
-                                       break;
-
-                               case DTK_YEAR:
-                                       *result = tm->tm_year;
-                                       break;
-
-                               case DTK_DECADE:
-                                       *result = (tm->tm_year / 10);
-                                       break;
-
-                               case DTK_CENTURY:
-                                       *result = (tm->tm_year / 100);
-                                       break;
-
-                               case DTK_MILLENIUM:
-                                       *result = (tm->tm_year / 1000);
-                                       break;
-
-                               default:
-                                       elog(ERROR, "Datetime units '%s' not supported", lowunits);
-                                       *result = 0;
-                       }
-
-               }
-               else if (type == RESERV)
-               {
-                       switch (val)
-                       {
-                               case DTK_EPOCH:
-                                       DATETIME_EPOCH(*result);
-                                       *result = dt - SetDateTime(*result);
-                                       break;
-
-                               case DTK_DOW:
-                                       if (datetime2tm(dt, &tz, tm, &fsec, &tzn) != 0)
-                                               elog(ERROR, "Unable to encode datetime");
-
-                                       *result = j2day(date2j(tm->tm_year, tm->tm_mon, tm->tm_mday));
-                                       break;
-
-                               case DTK_DOY:
-                                       if (datetime2tm(dt, &tz, tm, &fsec, &tzn) != 0)
-                                               elog(ERROR, "Unable to encode datetime");
-
-                                       *result = (date2j(tm->tm_year, tm->tm_mon, tm->tm_mday)
-                                                          - date2j(tm->tm_year, 1, 1) + 1);
-                                       break;
-
-                               default:
-                                       elog(ERROR, "Datetime units '%s' not supported", lowunits);
-                                       *result = 0;
-                       }
-
-               }
-               else
-               {
-                       elog(ERROR, "Datetime units '%s' not recognized", lowunits);
-                       *result = 0;
-               }
-       }
-
-       return result;
-}      /* datetime_part() */
-
-
-/* timespan_part()
- * Extract specified field from timespan.
- */
-float64
-timespan_part(text *units, TimeSpan *timespan)
-{
-       float64         result;
-
-       int                     type,
-                               val;
-       int                     i;
-       char       *up,
-                          *lp,
-                               lowunits[MAXDATELEN + 1];
-       double          fsec;
-       struct tm       tt,
-                          *tm = &tt;
-
-       if ((!PointerIsValid(units)) || (!PointerIsValid(timespan)))
-               return NULL;
-
-       result = palloc(sizeof(float64data));
-
-       up = VARDATA(units);
-       lp = lowunits;
-       for (i = 0; i < (VARSIZE(units) - VARHDRSZ); i++)
-               *lp++ = tolower(*up++);
-       *lp = '\0';
-
-       type = DecodeUnits(0, lowunits, &val);
-       if (type == IGNORE)
-               type = DecodeSpecial(0, lowunits, &val);
-
-       if (TIMESPAN_IS_INVALID(*timespan))
-       {
-#if NOT_USED
-               elog(ERROR, "Timespan is not finite");
-#endif
-               *result = 0;
-
-       }
-       else if (type == UNITS)
-       {
-
-               if (timespan2tm(*timespan, tm, &fsec) == 0)
-               {
-                       switch (val)
-                       {
-                               case DTK_MICROSEC:
-                                       *result = (fsec * 1000000);
-                                       break;
-
-                               case DTK_MILLISEC:
-                                       *result = (fsec * 1000);
-                                       break;
-
-                               case DTK_SECOND:
-                                       *result = (tm->tm_sec + fsec);
-                                       break;
-
-                               case DTK_MINUTE:
-                                       *result = tm->tm_min;
-                                       break;
-
-                               case DTK_HOUR:
-                                       *result = tm->tm_hour;
-                                       break;
-
-                               case DTK_DAY:
-                                       *result = tm->tm_mday;
-                                       break;
-
-                               case DTK_MONTH:
-                                       *result = tm->tm_mon;
-                                       break;
-
-                               case DTK_QUARTER:
-                                       *result = (tm->tm_mon / 4) + 1;
-                                       break;
-
-                               case DTK_YEAR:
-                                       *result = tm->tm_year;
-                                       break;
-
-                               case DTK_DECADE:
-                                       *result = (tm->tm_year / 10);
-                                       break;
-
-                               case DTK_CENTURY:
-                                       *result = (tm->tm_year / 100);
-                                       break;
-
-                               case DTK_MILLENIUM:
-                                       *result = (tm->tm_year / 1000);
-                                       break;
-
-                               default:
-                                       elog(ERROR, "Timespan units '%s' not yet supported", textout(units));
-                                       result = NULL;
-                       }
-
-               }
-               else
-               {
-                       elog(NOTICE, "Timespan out of range");
-                       *result = 0;
-               }
-
-       }
-       else if ((type == RESERV) && (val == DTK_EPOCH))
-       {
-               *result = timespan->time;
-               if (timespan->month != 0)
-               {
-                       *result += ((365.25 * 86400) * (timespan->month / 12));
-                       *result += ((30 * 86400) * (timespan->month % 12));
-               }
-
-       }
-       else
-       {
-               elog(ERROR, "Timespan units '%s' not recognized", textout(units));
-               *result = 0;
-       }
-
-       return result;
-}      /* timespan_part() */
-
-
-/* datetime_zone()
- * Encode datetime type with specified time zone.
- */
-text *
-datetime_zone(text *zone, DateTime *datetime)
-{
-       text       *result;
-
-       DateTime        dt;
-       int                     tz;
-       int                     type,
-                               val;
-       int                     i;
-       char       *up,
-                          *lp,
-                               lowzone[MAXDATELEN + 1];
-       char       *tzn,
-                               upzone[MAXDATELEN + 1];
-       double          fsec;
-       struct tm       tt,
-                          *tm = &tt;
-       char            buf[MAXDATELEN + 1];
-       int                     len;
-
-       if ((!PointerIsValid(zone)) || (!PointerIsValid(datetime)))
-               return NULL;
-
-       up = VARDATA(zone);
-       lp = lowzone;
-       for (i = 0; i < (VARSIZE(zone) - VARHDRSZ); i++)
-               *lp++ = tolower(*up++);
-       *lp = '\0';
-
-       type = DecodeSpecial(0, lowzone, &val);
-
-       if (DATETIME_NOT_FINITE(*datetime))
-       {
-
-               /*
-                * could return null but Postgres doesn't like that currently. -
-                * tgl 97/06/12
-                */
-               elog(ERROR, "Datetime is not finite");
-               result = NULL;
-
-       }
-       else if ((type == TZ) || (type == DTZ))
-       {
-               tm->tm_isdst = ((type == DTZ) ? 1 : 0);
-               tz = val * 60;
-
-               dt = (DATETIME_IS_RELATIVE(*datetime) ? SetDateTime(*datetime) : *datetime);
-               dt = dt2local(dt, tz);
-
-               if (datetime2tm(dt, NULL, tm, &fsec, NULL) != 0)
-                       elog(ERROR, "Datetime not legal");
-
-               up = upzone;
-               lp = lowzone;
-               for (i = 0; *lp != '\0'; i++)
-                       *up++ = toupper(*lp++);
-               *up = '\0';
-
-               tzn = upzone;
-               EncodeDateTime(tm, fsec, &tz, &tzn, DateStyle, buf);
-
-               len = (strlen(buf) + VARHDRSZ);
-
-               result = palloc(len);
-
-               VARSIZE(result) = len;
-               memmove(VARDATA(result), buf, (len - VARHDRSZ));
-
-       }
-       else
-       {
-               elog(ERROR, "Time zone '%s' not recognized", lowzone);
-               result = NULL;
-       }
-
-       return result;
-}      /* datetime_zone() */
-
-
-/*****************************************************************************
- *      PRIVATE ROUTINES                                                                                                                *
- *****************************************************************************/
-
-/* definitions for squeezing values into "value" */
-#define ABS_SIGNBIT            (char) 0200
-#define VALMASK                        (char) 0177
-#define NEG(n)                 ((n)|ABS_SIGNBIT)
-#define SIGNEDCHAR(c)  ((c)&ABS_SIGNBIT? -((c)&VALMASK): (c))
-#define FROMVAL(tp)            (-SIGNEDCHAR((tp)->value) * 10) /* uncompress */
-#define TOVAL(tp, v)   ((tp)->value = ((v) < 0? NEG((-(v))/10): (v)/10))
-
-/*
- * to keep this table reasonably small, we divide the lexval for TZ and DTZ
- * entries by 10 and truncate the text field at MAXTOKLEN characters.
- * the text field is not guaranteed to be NULL-terminated.
- */
-static datetkn datetktbl[] = {
-/*             text                    token   lexval */
-       {EARLY, RESERV, DTK_EARLY}, /* "-infinity" reserved for "early time" */
-       {"acsst", DTZ, 63},                     /* Cent. Australia */
-       {"acst", TZ, 57},                       /* Cent. Australia */
-       {DA_D, ADBC, AD},                       /* "ad" for years >= 0 */
-       {"abstime", IGNORE, 0},         /* "abstime" for pre-v6.1 "Invalid
-                                                                * Abstime" */
-       {"adt", DTZ, NEG(18)},          /* Atlantic Daylight Time */
-       {"aesst", DTZ, 66},                     /* E. Australia */
-       {"aest", TZ, 60},                       /* Australia Eastern Std Time */
-       {"ahst", TZ, NEG(60)},          /* Alaska-Hawaii Std Time */
-       {"allballs", RESERV, DTK_ZULU},         /* 00:00:00 */
-       {"am", AMPM, AM},
-       {"apr", MONTH, 4},
-       {"april", MONTH, 4},
-       {"ast", TZ, NEG(24)},           /* Atlantic Std Time (Canada) */
-       {"at", IGNORE, 0},                      /* "at" (throwaway) */
-       {"aug", MONTH, 8},
-       {"august", MONTH, 8},
-       {"awsst", DTZ, 54},                     /* W. Australia */
-       {"awst", TZ, 48},                       /* W. Australia */
-       {DB_C, ADBC, BC},                       /* "bc" for years < 0 */
-       {"bst", TZ, 6},                         /* British Summer Time */
-       {"bt", TZ, 18},                         /* Baghdad Time */
-       {"cadt", DTZ, 63},                      /* Central Australian DST */
-       {"cast", TZ, 57},                       /* Central Australian ST */
-       {"cat", TZ, NEG(60)},           /* Central Alaska Time */
-       {"cct", TZ, 48},                        /* China Coast */
-       {"cdt", DTZ, NEG(30)},          /* Central Daylight Time */
-       {"cet", TZ, 6},                         /* Central European Time */
-       {"cetdst", DTZ, 12},            /* Central European Dayl.Time */
-#if USE_AUSTRALIAN_RULES
-       {"cst", TZ, 63},                        /* Australia Eastern Std Time */
-#else
-       {"cst", TZ, NEG(36)},           /* Central Standard Time */
-#endif
-       {DCURRENT, RESERV, DTK_CURRENT},        /* "current" is always now */
-       {"dec", MONTH, 12},
-       {"december", MONTH, 12},
-       {"dnt", TZ, 6},                         /* Dansk Normal Tid */
-       {"dow", RESERV, DTK_DOW},       /* day of week */
-       {"doy", RESERV, DTK_DOY},       /* day of year */
-       {"dst", DTZMOD, 6},
-       {"east", TZ, 60},                       /* East Australian Std Time */
-       {"edt", DTZ, NEG(24)},          /* Eastern Daylight Time */
-       {"eet", TZ, 12},                        /* East. Europe, USSR Zone 1 */
-       {"eetdst", DTZ, 18},            /* Eastern Europe */
-       {EPOCH, RESERV, DTK_EPOCH}, /* "epoch" reserved for system epoch time */
-#if USE_AUSTRALIAN_RULES
-       {"est", TZ, 60},                        /* Australia Eastern Std Time */
-#else
-       {"est", TZ, NEG(30)},           /* Eastern Standard Time */
-#endif
-       {"feb", MONTH, 2},
-       {"february", MONTH, 2},
-       {"fri", DOW, 5},
-       {"friday", DOW, 5},
-       {"fst", TZ, 6},                         /* French Summer Time */
-       {"fwt", DTZ, 12},                       /* French Winter Time  */
-       {"gmt", TZ, 0},                         /* Greenwish Mean Time */
-       {"gst", TZ, 60},                        /* Guam Std Time, USSR Zone 9 */
-       {"hdt", DTZ, NEG(54)},          /* Hawaii/Alaska */
-       {"hmt", DTZ, 18},                       /* Hellas ? ? */
-       {"hst", TZ, NEG(60)},           /* Hawaii Std Time */
-       {"idle", TZ, 72},                       /* Intl. Date Line, East */
-       {"idlw", TZ, NEG(72)},          /* Intl. Date Line, West */
-       {LATE, RESERV, DTK_LATE},       /* "infinity" reserved for "late time" */
-       {INVALID, RESERV, DTK_INVALID},
-       /* "invalid" reserved for invalid time */
-       {"ist", TZ, 12},                        /* Israel */
-       {"it", TZ, 21},                         /* Iran Time */
-       {"jan", MONTH, 1},
-       {"january", MONTH, 1},
-       {"jst", TZ, 54},                        /* Japan Std Time,USSR Zone 8 */
-       {"jt", TZ, 45},                         /* Java Time */
-       {"jul", MONTH, 7},
-       {"july", MONTH, 7},
-       {"jun", MONTH, 6},
-       {"june", MONTH, 6},
-       {"kst", TZ, 54},                        /* Korea Standard Time */
-       {"ligt", TZ, 60},                       /* From Melbourne, Australia */
-       {"mar", MONTH, 3},
-       {"march", MONTH, 3},
-       {"may", MONTH, 5},
-       {"mdt", DTZ, NEG(36)},          /* Mountain Daylight Time */
-       {"mest", DTZ, 12},                      /* Middle Europe Summer Time */
-       {"met", TZ, 6},                         /* Middle Europe Time */
-       {"metdst", DTZ, 12},            /* Middle Europe Daylight Time */
-       {"mewt", TZ, 6},                        /* Middle Europe Winter Time */
-       {"mez", TZ, 6},                         /* Middle Europe Zone */
-       {"mon", DOW, 1},
-       {"monday", DOW, 1},
-       {"mst", TZ, NEG(42)},           /* Mountain Standard Time */
-       {"mt", TZ, 51},                         /* Moluccas Time */
-       {"ndt", DTZ, NEG(15)},          /* Nfld. Daylight Time */
-       {"nft", TZ, NEG(21)},           /* Newfoundland Standard Time */
-       {"nor", TZ, 6},                         /* Norway Standard Time */
-       {"nov", MONTH, 11},
-       {"november", MONTH, 11},
-       {NOW, RESERV, DTK_NOW},         /* current transaction time */
-       {"nst", TZ, NEG(21)},           /* Nfld. Standard Time */
-       {"nt", TZ, NEG(66)},            /* Nome Time */
-       {"nzdt", DTZ, 78},                      /* New Zealand Daylight Time */
-       {"nzst", TZ, 72},                       /* New Zealand Standard Time */
-       {"nzt", TZ, 72},                        /* New Zealand Time */
-       {"oct", MONTH, 10},
-       {"october", MONTH, 10},
-       {"on", IGNORE, 0},                      /* "on" (throwaway) */
-       {"pdt", DTZ, NEG(42)},          /* Pacific Daylight Time */
-       {"pm", AMPM, PM},
-       {"pst", TZ, NEG(48)},           /* Pacific Standard Time */
-       {"sadt", DTZ, 63},                      /* S. Australian Dayl. Time */
-       {"sast", TZ, 57},                       /* South Australian Std Time */
-       {"sat", DOW, 6},
-       {"saturday", DOW, 6},
-       {"sep", MONTH, 9},
-       {"sept", MONTH, 9},
-       {"september", MONTH, 9},
-       {"set", TZ, NEG(6)},            /* Seychelles Time ?? */
-       {"sst", DTZ, 12},                       /* Swedish Summer Time */
-       {"sun", DOW, 0},
-       {"sunday", DOW, 0},
-       {"swt", TZ, 6},                         /* Swedish Winter Time  */
-       {"thu", DOW, 4},
-       {"thur", DOW, 4},
-       {"thurs", DOW, 4},
-       {"thursday", DOW, 4},
-       {TODAY, RESERV, DTK_TODAY}, /* midnight */
-       {TOMORROW, RESERV, DTK_TOMORROW},       /* tomorrow midnight */
-       {"tue", DOW, 2},
-       {"tues", DOW, 2},
-       {"tuesday", DOW, 2},
-       {"undefined", RESERV, DTK_INVALID}, /* "undefined" pre-v6.1 invalid
-                                                                                * time */
-       {"ut", TZ, 0},
-       {"utc", TZ, 0},
-       {"wadt", DTZ, 48},                      /* West Australian DST */
-       {"wast", TZ, 42},                       /* West Australian Std Time */
-       {"wat", TZ, NEG(6)},            /* West Africa Time */
-       {"wdt", DTZ, 54},                       /* West Australian DST */
-       {"wed", DOW, 3},
-       {"wednesday", DOW, 3},
-       {"weds", DOW, 3},
-       {"wet", TZ, 0},                         /* Western Europe */
-       {"wetdst", DTZ, 6},                     /* Western Europe */
-       {"wst", TZ, 48},                        /* West Australian Std Time */
-       {"ydt", DTZ, NEG(48)},          /* Yukon Daylight Time */
-       {YESTERDAY, RESERV, DTK_YESTERDAY}, /* yesterday midnight */
-       {"yst", TZ, NEG(54)},           /* Yukon Standard Time */
-       {"zp4", TZ, NEG(24)},           /* GMT +4  hours. */
-       {"zp5", TZ, NEG(30)},           /* GMT +5  hours. */
-       {"zp6", TZ, NEG(36)},           /* GMT +6  hours. */
-       {"z", RESERV, DTK_ZULU},        /* 00:00:00 */
-       {ZULU, RESERV, DTK_ZULU},       /* 00:00:00 */
-};
-
-static unsigned int szdatetktbl = sizeof datetktbl / sizeof datetktbl[0];
-
-static datetkn deltatktbl[] = {
-/*             text                    token   lexval */
-       {"@", IGNORE, 0},                       /* postgres relative time prefix */
-       {DAGO, AGO, 0},                         /* "ago" indicates negative time offset */
-       {"c", UNITS, DTK_CENTURY},      /* "century" relative time units */
-       {"cent", UNITS, DTK_CENTURY},           /* "century" relative time units */
-       {"centuries", UNITS, DTK_CENTURY},      /* "centuries" relative time units */
-       {DCENTURY, UNITS, DTK_CENTURY},         /* "century" relative time units */
-       {"d", UNITS, DTK_DAY},          /* "day" relative time units */
-       {DDAY, UNITS, DTK_DAY},         /* "day" relative time units */
-       {"days", UNITS, DTK_DAY},       /* "days" relative time units */
-       {"dec", UNITS, DTK_DECADE}, /* "decade" relative time units */
-       {"decs", UNITS, DTK_DECADE},/* "decades" relative time units */
-       {DDECADE, UNITS, DTK_DECADE},           /* "decade" relative time units */
-       {"decades", UNITS, DTK_DECADE},         /* "decades" relative time units */
-       {"h", UNITS, DTK_HOUR},         /* "hour" relative time units */
-       {DHOUR, UNITS, DTK_HOUR},       /* "hour" relative time units */
-       {"hours", UNITS, DTK_HOUR}, /* "hours" relative time units */
-       {"hr", UNITS, DTK_HOUR},        /* "hour" relative time units */
-       {"hrs", UNITS, DTK_HOUR},       /* "hours" relative time units */
-       {INVALID, RESERV, DTK_INVALID},         /* "invalid" reserved for invalid
-                                                                                * time */
-       {"m", UNITS, DTK_MINUTE},       /* "minute" relative time units */
-       {"microsecon", UNITS, DTK_MICROSEC},            /* "microsecond" relative
-                                                                                                * time units */
-       {"mil", UNITS, DTK_MILLENIUM},          /* "millenium" relative time units */
-       {"mils", UNITS, DTK_MILLENIUM},         /* "millenia" relative time units */
-       {"millenia", UNITS, DTK_MILLENIUM}, /* "millenia" relative time units */
-       {DMILLENIUM, UNITS, DTK_MILLENIUM}, /* "millenium" relative time units */
-       {"millisecon", UNITS, DTK_MILLISEC},            /* relative time units */
-       {"min", UNITS, DTK_MINUTE}, /* "minute" relative time units */
-       {"mins", UNITS, DTK_MINUTE},/* "minutes" relative time units */
-       {"mins", UNITS, DTK_MINUTE},/* "minutes" relative time units */
-       {DMINUTE, UNITS, DTK_MINUTE},           /* "minute" relative time units */
-       {"minutes", UNITS, DTK_MINUTE},         /* "minutes" relative time units */
-       {"mon", UNITS, DTK_MONTH},      /* "months" relative time units */
-       {"mons", UNITS, DTK_MONTH}, /* "months" relative time units */
-       {DMONTH, UNITS, DTK_MONTH}, /* "month" relative time units */
-       {"months", UNITS, DTK_MONTH},
-       {"ms", UNITS, DTK_MILLISEC},
-       {"msec", UNITS, DTK_MILLISEC},
-       {DMILLISEC, UNITS, DTK_MILLISEC},
-       {"mseconds", UNITS, DTK_MILLISEC},
-       {"msecs", UNITS, DTK_MILLISEC},
-       {"qtr", UNITS, DTK_QUARTER},/* "quarter" relative time */
-       {DQUARTER, UNITS, DTK_QUARTER},         /* "quarter" relative time */
-       {"reltime", IGNORE, 0},         /* for pre-v6.1 "Undefined Reltime" */
-       {"s", UNITS, DTK_SECOND},
-       {"sec", UNITS, DTK_SECOND},
-       {DSECOND, UNITS, DTK_SECOND},
-       {"seconds", UNITS, DTK_SECOND},
-       {"secs", UNITS, DTK_SECOND},
-       {DTIMEZONE, UNITS, DTK_TZ}, /* "timezone" time offset */
-       {"tz", UNITS, DTK_TZ},          /* "timezone" time offset */
-       {"tz_hour", UNITS, DTK_TZ_HOUR},        /* timezone hour units */
-       {"tz_minute", UNITS, DTK_TZ_MINUTE},            /* timezone minutes units */
-       {"undefined", RESERV, DTK_INVALID}, /* pre-v6.1 invalid time */
-       {"us", UNITS, DTK_MICROSEC},/* "microsecond" relative time units */
-       {"usec", UNITS, DTK_MICROSEC},          /* "microsecond" relative time
-                                                                                * units */
-       {DMICROSEC, UNITS, DTK_MICROSEC},       /* "microsecond" relative time
-                                                                                * units */
-       {"useconds", UNITS, DTK_MICROSEC},      /* "microseconds" relative time
-                                                                                * units */
-       {"usecs", UNITS, DTK_MICROSEC},         /* "microseconds" relative time
-                                                                                * units */
-       {"w", UNITS, DTK_WEEK},         /* "week" relative time units */
-       {DWEEK, UNITS, DTK_WEEK},       /* "week" relative time units */
-       {"weeks", UNITS, DTK_WEEK}, /* "weeks" relative time units */
-       {"y", UNITS, DTK_YEAR},         /* "year" relative time units */
-       {DYEAR, UNITS, DTK_YEAR},       /* "year" relative time units */
-       {"years", UNITS, DTK_YEAR}, /* "years" relative time units */
-       {"yr", UNITS, DTK_YEAR},        /* "year" relative time units */
-       {"yrs", UNITS, DTK_YEAR},       /* "years" relative time units */
-};
-
-static unsigned int szdeltatktbl = sizeof deltatktbl / sizeof deltatktbl[0];
-
-#if USE_DATE_CACHE
-datetkn    *datecache[MAXDATEFIELDS] = {NULL};
-
-datetkn    *deltacache[MAXDATEFIELDS] = {NULL};
-
-#endif
-
-
-/*
- * Calendar time to Julian date conversions.
- * Julian date is commonly used in astronomical applications,
- *     since it is numerically accurate and computationally simple.
- * The algorithms here will accurately convert between Julian day
- *     and calendar date for all non-negative Julian days
- *     (i.e. from Nov 23, -4713 on).
- *
- * Ref: Explanatory Supplement to the Astronomical Almanac, 1992.
- *     University Science Books, 20 Edgehill Rd. Mill Valley CA 94941.
- *
- * Use the algorithm by Henry Fliegel, a former NASA/JPL colleague
- *     now at Aerospace Corp. (hi, Henry!)
- *
- * These routines will be used by other date/time packages - tgl 97/02/25
- */
-
-int
-date2j(int y, int m, int d)
-{
-       int                     m12 = (m - 14) / 12;
-
-       return ((1461 * (y + 4800 + m12)) / 4 + (367 * (m - 2 - 12 * (m12))) / 12
-                       - (3 * ((y + 4900 + m12) / 100)) / 4 + d - 32075);
-}      /* date2j() */
-
-void
-j2date(int jd, int *year, int *month, int *day)
-{
-       int                     j,
-                               y,
-                               m,
-                               d;
-
-       int                     i,
-                               l,
-                               n;
-
-       l = jd + 68569;
-       n = (4 * l) / 146097;
-       l -= (146097 * n + 3) / 4;
-       i = (4000 * (l + 1)) / 1461001;
-       l += 31 - (1461 * i) / 4;
-       j = (80 * l) / 2447;
-       d = l - (2447 * j) / 80;
-       l = j / 11;
-       m = (j + 2) - (12 * l);
-       y = 100 * (n - 49) + i + l;
-
-       *year = y;
-       *month = m;
-       *day = d;
-       return;
-}      /* j2date() */
-
-static int
-j2day(int date)
-{
-       int                     day;
-
-       day = (date + 1) % 7;
-
-       return day;
-}      /* j2day() */
-
-
-/* datetime2tm()
- * Convert datetime data type to POSIX time structure.
- * Note that year is _not_ 1900-based, but is an explicit full value.
- * Also, month is one-based, _not_ zero-based.
- * Returns:
- *      0 on success
- *     -1 on out of range
- *
- * For dates within the system-supported time_t range, convert to the
- *     local time zone. If out of this range, leave as GMT. - tgl 97/05/27
- */
-int
-datetime2tm(DateTime dt, int *tzp, struct tm * tm, double *fsec, char **tzn)
-{
-       double          date,
-                               date0,
-                               time,
-                               sec;
-       time_t          utime;
-
-#ifdef USE_POSIX_TIME
-       struct tm  *tx;
-
-#endif
-
-       date0 = date2j(2000, 1, 1);
-
-       time = dt;
-       TMODULO(time, date, 86400e0);
-
-       if (time < 0)
-       {
-               time += 86400;
-               date -= 1;
-       }
-
-       /* Julian day routine does not work for negative Julian days */
-       if (date < -date0)
-               return -1;
-
-       /* add offset to go from J2000 back to standard Julian date */
-       date += date0;
-
-       j2date((int) date, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
-       dt2time(time, &tm->tm_hour, &tm->tm_min, &sec);
-
-       *fsec = JROUND(sec);
-       TMODULO(*fsec, tm->tm_sec, 1e0);
-
-       if (tzp != NULL)
-       {
-               if (IS_VALID_UTIME(tm->tm_year, tm->tm_mon, tm->tm_mday))
-               {
-                       utime = (dt + (date0 - date2j(1970, 1, 1)) * 86400);
-
-#ifdef USE_POSIX_TIME
-                       tx = localtime(&utime);
-                       tm->tm_year = tx->tm_year + 1900;
-                       tm->tm_mon = tx->tm_mon + 1;
-                       tm->tm_mday = tx->tm_mday;
-                       tm->tm_hour = tx->tm_hour;
-                       tm->tm_min = tx->tm_min;
-#if NOT_USED
-/* XXX HACK
- * Argh! My Linux box puts in a 1 second offset for dates less than 1970
- *     but only if the seconds field was non-zero. So, don't copy the seconds
- *     field and instead carry forward from the original - tgl 97/06/18
- * Note that GNU/Linux uses the standard freeware zic package as do
- *     many other platforms so this may not be GNU/Linux/ix86-specific.
- */
-                       tm->tm_sec = tx->tm_sec;
-#endif
-                       tm->tm_isdst = tx->tm_isdst;
-
-#if defined(HAVE_TM_ZONE)
-                       tm->tm_gmtoff = tx->tm_gmtoff;
-                       tm->tm_zone = tx->tm_zone;
-
-                       *tzp = -(tm->tm_gmtoff);        /* tm_gmtoff is Sun/DEC-ism */
-                       if (tzn != NULL)
-                               *tzn = (char *) tm->tm_zone;
-#elif defined(HAVE_INT_TIMEZONE)
-#ifdef __CYGWIN__
-                       *tzp = (tm->tm_isdst ? (_timezone - 3600) : _timezone);
-#else
-                       *tzp = (tm->tm_isdst ? (timezone - 3600) : timezone);
-#endif
-                       if (tzn != NULL)
-                               *tzn = tzname[(tm->tm_isdst > 0)];
-#else
-#error USE_POSIX_TIME is defined but neither HAVE_TM_ZONE or HAVE_INT_TIMEZONE are defined
-#endif
-
-#else                                                  /* !USE_POSIX_TIME */
-                       *tzp = CTimeZone;       /* V7 conventions; don't know timezone? */
-                       if (tzn != NULL)
-                               *tzn = CTZName;
-#endif
-
-               }
-               else
-               {
-                       *tzp = 0;
-                       tm->tm_isdst = 0;
-                       if (tzn != NULL)
-                               *tzn = NULL;
-               }
-
-               dt = dt2local(dt, *tzp);
-
-       }
-       else
-       {
-               tm->tm_isdst = 0;
-               if (tzn != NULL)
-                       *tzn = NULL;
-       }
-
-       return 0;
-}      /* datetime2tm() */
-
-
-/* tm2datetime()
- * Convert a tm structure to a datetime data type.
- * Note that year is _not_ 1900-based, but is an explicit full value.
- * Also, month is one-based, _not_ zero-based.
- */
-int
-tm2datetime(struct tm * tm, double fsec, int *tzp, DateTime *result)
-{
-
-       double          date,
-                               time;
-
-       /* Julian day routines are not correct for negative Julian days */
-       if (!IS_VALID_JULIAN(tm->tm_year, tm->tm_mon, tm->tm_mday))
-               return -1;
-
-       date = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - date2j(2000, 1, 1);
-       time = time2t(tm->tm_hour, tm->tm_min, (tm->tm_sec + fsec));
-       *result = (date * 86400 + time);
-       if (tzp != NULL)
-               *result = dt2local(*result, -(*tzp));
-
-       return 0;
-}      /* tm2datetime() */
-
-
-/* timespan2tm()
- * Convert a timespan data type to a tm structure.
- */
-static int
-timespan2tm(TimeSpan span, struct tm * tm, float8 *fsec)
-{
-       double          time;
-
-       if (span.month != 0)
-       {
-               tm->tm_year = span.month / 12;
-               tm->tm_mon = span.month % 12;
-
-       }
-       else
-       {
-               tm->tm_year = 0;
-               tm->tm_mon = 0;
-       }
-
-#ifdef ROUND_ALL
-       time = JROUND(span.time);
-#else
-       time = span.time;
-#endif
-
-       TMODULO(time, tm->tm_mday, 86400e0);
-       TMODULO(time, tm->tm_hour, 3600e0);
-       TMODULO(time, tm->tm_min, 60e0);
-       TMODULO(time, tm->tm_sec, 1e0);
-       *fsec = time;
-
-       return 0;
-}      /* timespan2tm() */
-
-static int
-tm2timespan(struct tm * tm, double fsec, TimeSpan *span)
-{
-       span->month = ((tm->tm_year * 12) + tm->tm_mon);
-       span->time = ((((((tm->tm_mday * 24.0)
-                                        + tm->tm_hour) * 60.0)
-                                        + tm->tm_min) * 60.0)
-                                        + tm->tm_sec);
-       span->time = JROUND(span->time + fsec);
-
-       return 0;
-}      /* tm2timespan() */
-
-
-static DateTime
-dt2local(DateTime dt, int tz)
-{
-       dt -= tz;
-       dt = JROUND(dt);
-       return dt;
-}      /* dt2local() */
-
-static double
-time2t(const int hour, const int min, const double sec)
-{
-       return (((hour * 60) + min) * 60) + sec;
-}      /* time2t() */
-
-static void
-dt2time(DateTime jd, int *hour, int *min, double *sec)
-{
-       double          time;
-
-       time = jd;
-
-       *hour = (time / 3600);
-       time -= ((*hour) * 3600);
-       *min = (time / 60);
-       time -= ((*min) * 60);
-       *sec = JROUND(time);
-
-       return;
-}      /* dt2time() */
-
-
-/*
- * parse and convert date in timestr (the normal interface)
- *
- * Returns the number of seconds since epoch (J2000)
- */
-
-/* ParseDateTime()
- * Break string into tokens based on a date/time context.
- */
-int
-ParseDateTime(char *timestr, char *lowstr,
-                         char **field, int *ftype, int maxfields, int *numfields)
-{
-       int                     nf = 0;
-       char       *cp = timestr;
-       char       *lp = lowstr;
-
-       /* outer loop through fields */
-       while (*cp != '\0')
-       {
-               field[nf] = lp;
-
-               /* leading digit? then date or time */
-               if (isdigit(*cp) || (*cp == '.'))
-               {
-                       *lp++ = *cp++;
-                       while (isdigit(*cp))
-                               *lp++ = *cp++;
-                       /* time field? */
-                       if (*cp == ':')
-                       {
-                               ftype[nf] = DTK_TIME;
-                               while (isdigit(*cp) || (*cp == ':') || (*cp == '.'))
-                                       *lp++ = *cp++;
-
-                       }
-                       /* date field? allow embedded text month */
-                       else if ((*cp == '-') || (*cp == '/') || (*cp == '.'))
-                       {
-                               ftype[nf] = DTK_DATE;
-                               while (isalnum(*cp) || (*cp == '-') || (*cp == '/') || (*cp == '.'))
-                                       *lp++ = tolower(*cp++);
-
-                       }
-
-                       /*
-                        * otherwise, number only and will determine year, month, or
-                        * day later
-                        */
-                       else
-                               ftype[nf] = DTK_NUMBER;
-
-               }
-
-               /*
-                * text? then date string, month, day of week, special, or
-                * timezone
-                */
-               else if (isalpha(*cp))
-               {
-                       ftype[nf] = DTK_STRING;
-                       *lp++ = tolower(*cp++);
-                       while (isalpha(*cp))
-                               *lp++ = tolower(*cp++);
-
-                       /* full date string with leading text month? */
-                       if ((*cp == '-') || (*cp == '/') || (*cp == '.'))
-                       {
-                               /*
-                                * special case of Posix timezone "GMT-0800"
-                                * Note that other sign (e.g. "GMT+0800"
-                                * is recognized as two separate fields and handled later.
-                                * XXX There is no room for a delimiter between
-                                * the "GMT" and the "-0800", so we are going to just swallow the "GMT".
-                                * But this leads to other troubles with the definition of signs,
-                                * so we have to flip
-                                * - thomas 2000-02-06
-                                */
-                               if ((*cp == '-') && isdigit(*(cp+1))
-                                       && (strncmp(field[nf], "gmt", 3) == 0))
-                               {
-                                       *cp = '+';
-                                       continue;
-                               }
-
-                               ftype[nf] = DTK_DATE;
-                               while (isdigit(*cp) || (*cp == '-') || (*cp == '/') || (*cp == '.'))
-                                       *lp++ = tolower(*cp++);
-                       }
-
-                       /* skip leading spaces */
-               }
-               else if (isspace(*cp))
-               {
-                       cp++;
-                       continue;
-
-                       /* sign? then special or numeric timezone */
-               }
-               else if ((*cp == '+') || (*cp == '-'))
-               {
-                       *lp++ = *cp++;
-                       /* soak up leading whitespace */
-                       while (isspace(*cp))
-                               cp++;
-                       /* numeric timezone? */
-                       if (isdigit(*cp))
-                       {
-                               ftype[nf] = DTK_TZ;
-                               *lp++ = *cp++;
-                               while (isdigit(*cp) || (*cp == ':'))
-                                       *lp++ = *cp++;
-
-                               /* special? */
-                       }
-                       else if (isalpha(*cp))
-                       {
-                               ftype[nf] = DTK_SPECIAL;
-                               *lp++ = tolower(*cp++);
-                               while (isalpha(*cp))
-                                       *lp++ = tolower(*cp++);
-
-                               /* otherwise something wrong... */
-                       }
-                       else
-                               return -1;
-
-                       /* ignore punctuation but use as delimiter */
-               }
-               else if (ispunct(*cp))
-               {
-                       cp++;
-                       continue;
-
-               }
-               else
-                       return -1;
-
-               /* force in a delimiter */
-               *lp++ = '\0';
-               nf++;
-               if (nf > MAXDATEFIELDS)
-                       return -1;
-       }
-
-       *numfields = nf;
-
-       return 0;
-}      /* ParseDateTime() */
-
-
-/* DecodeDateTime()
- * Interpret previously parsed fields for general date and time.
- * Return 0 if full date, 1 if only time, and -1 if problems.
- *             External format(s):
- *                             "<weekday> <month>-<day>-<year> <hour>:<minute>:<second>"
- *                             "Fri Feb-7-1997 15:23:27"
- *                             "Feb-7-1997 15:23:27"
- *                             "2-7-1997 15:23:27"
- *                             "1997-2-7 15:23:27"
- *                             "1997.038 15:23:27"             (day of year 1-366)
- *             Also supports input in compact time:
- *                             "970207 152327"
- *                             "97038 152327"
- *
- * Use the system-provided functions to get the current time zone
- *     if not specified in the input string.
- * If the date is outside the time_t system-supported time range,
- *     then assume GMT time zone. - tgl 97/05/27
- */
-int
-DecodeDateTime(char **field, int *ftype, int nf,
-                          int *dtype, struct tm * tm, double *fsec, int *tzp)
-{
-       int                     fmask = 0,
-                               tmask,
-                               type;
-       int                     i;
-       int                     flen,
-                               val;
-       int                     mer = HR24;
-       int                     haveTextMonth = FALSE;
-       int                     is2digits = FALSE;
-       int                     bc = FALSE;
-
-       *dtype = DTK_DATE;
-       tm->tm_hour = 0;
-       tm->tm_min = 0;
-       tm->tm_sec = 0;
-       *fsec = 0;
-       tm->tm_isdst = -1;                      /* don't know daylight savings time status
-                                                                * apriori */
-       if (tzp != NULL)
-               *tzp = 0;
-
-       for (i = 0; i < nf; i++)
-       {
-               switch (ftype[i])
-               {
-                       case DTK_DATE:
-                               if (DecodeDate(field[i], fmask, &tmask, tm) != 0)
-                                       return -1;
-                               break;
-
-                       case DTK_TIME:
-                               if (DecodeTime(field[i], fmask, &tmask, tm, fsec) != 0)
-                                       return -1;
-
-                               /*
-                                * check upper limit on hours; other limits checked in
-                                * DecodeTime()
-                                */
-                               if (tm->tm_hour > 23)
-                                       return -1;
-                               break;
-
-                       case DTK_TZ:
-                               if (tzp == NULL)
-                                       return -1;
-                               if (DecodeTimezone(field[i], tzp) != 0)
-                                       return -1;
-                               tmask = DTK_M(TZ);
-                               break;
-
-                       case DTK_NUMBER:
-                               flen = strlen(field[i]);
-
-                               /*
-                                * long numeric string and either no date or no time read
-                                * yet? then interpret as a concatenated date or time...
-                                */
-                               if ((flen > 4) && !((fmask & DTK_DATE_M) && (fmask & DTK_TIME_M)))
-                               {
-                                       if (DecodeNumberField(flen, field[i], fmask, &tmask, tm, fsec, &is2digits) != 0)
-                                               return -1;
-
-                               }
-                               /* otherwise it is a single date/time field... */
-                               else
-                               {
-                                       if (DecodeNumber(flen, field[i], fmask, &tmask, tm, fsec, &is2digits) != 0)
-                                               return -1;
-                               }
-                               break;
-
-                       case DTK_STRING:
-                       case DTK_SPECIAL:
-                               type = DecodeSpecial(i, field[i], &val);
-                               if (type == IGNORE)
-                                       continue;
-
-                               tmask = DTK_M(type);
-                               switch (type)
-                               {
-                                       case RESERV:
-                                               switch (val)
-                                               {
-                                                       case DTK_NOW:
-                                                               tmask = (DTK_DATE_M | DTK_TIME_M | DTK_M(TZ));
-                                                               *dtype = DTK_DATE;
-                                                               GetCurrentTime(tm);
-                                                               if (tzp != NULL)
-                                                                       *tzp = CTimeZone;
-                                                               break;
-
-                                                       case DTK_YESTERDAY:
-                                                               tmask = DTK_DATE_M;
-                                                               *dtype = DTK_DATE;
-                                                               GetCurrentTime(tm);
-                                                               j2date((date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - 1),
-                                                               &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
-                                                               tm->tm_hour = 0;
-                                                               tm->tm_min = 0;
-                                                               tm->tm_sec = 0;
-                                                               break;
-
-                                                       case DTK_TODAY:
-                                                               tmask = DTK_DATE_M;
-                                                               *dtype = DTK_DATE;
-                                                               GetCurrentTime(tm);
-                                                               tm->tm_hour = 0;
-                                                               tm->tm_min = 0;
-                                                               tm->tm_sec = 0;
-                                                               break;
-
-                                                       case DTK_TOMORROW:
-                                                               tmask = DTK_DATE_M;
-                                                               *dtype = DTK_DATE;
-                                                               GetCurrentTime(tm);
-                                                               j2date((date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) + 1),
-                                                               &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
-                                                               tm->tm_hour = 0;
-                                                               tm->tm_min = 0;
-                                                               tm->tm_sec = 0;
-                                                               break;
-
-                                                       case DTK_ZULU:
-                                                               tmask = (DTK_TIME_M | DTK_M(TZ));
-                                                               *dtype = DTK_DATE;
-                                                               tm->tm_hour = 0;
-                                                               tm->tm_min = 0;
-                                                               tm->tm_sec = 0;
-                                                               if (tzp != NULL)
-                                                                       *tzp = 0;
-                                                               break;
-
-                                                       default:
-                                                               *dtype = val;
-                                               }
-
-                                               break;
-
-                                       case MONTH:
-                                               /*
-                                                * already have a (numeric) month? then see if we
-                                                * can substitute...
-                                                */
-                                               if ((fmask & DTK_M(MONTH)) && (!haveTextMonth)
-                                                       && (!(fmask & DTK_M(DAY)))
-                                                       && ((tm->tm_mon >= 1) && (tm->tm_mon <= 31)))
-                                               {
-                                                       tm->tm_mday = tm->tm_mon;
-                                                       tmask = DTK_M(DAY);
-                                               }
-                                               haveTextMonth = TRUE;
-                                               tm->tm_mon = val;
-                                               break;
-
-                                       case DTZMOD:
-
-                                               /*
-                                                * daylight savings time modifier (solves "MET
-                                                * DST" syntax)
-                                                */
-                                               tmask |= DTK_M(DTZ);
-                                               tm->tm_isdst = 1;
-                                               if (tzp == NULL)
-                                                       return -1;
-                                               *tzp += val * 60;
-                                               break;
-
-                                       case DTZ:
-
-                                               /*
-                                                * set mask for TZ here _or_ check for DTZ later
-                                                * when getting default timezone
-                                                */
-                                               tmask |= DTK_M(TZ);
-                                               tm->tm_isdst = 1;
-                                               if (tzp == NULL)
-                                                       return -1;
-                                               *tzp = val * 60;
-                                               break;
-
-                                       case TZ:
-                                               tm->tm_isdst = 0;
-                                               if (tzp == NULL)
-                                                       return -1;
-                                               *tzp = val * 60;
-
-                                               /* Swallow an immediately succeeding timezone if this is GMT
-                                                * This handles the odd case in FreeBSD of "GMT+0800"
-                                                * but note that we need to flip the sign on this too.
-                                                * Claims to be some sort of POSIX standard format :(
-                                                * - thomas 2000-01-20
-                                                */
-                                               if ((i < (nf-1)) && (ftype[i+1] == DTK_TZ)
-                                                       && (strcmp(field[i], "gmt") == 0))
-                                               {
-                                                       i++;
-                                                       if (DecodeTimezone(field[i], tzp) != 0)
-                                                               return -1;
-
-                                                       /* flip the sign per POSIX standard */
-                                                       *tzp = -(*tzp);
-                                               }
-
-
-                                               break;
-
-                                       case IGNORE:
-                                               break;
-
-                                       case AMPM:
-                                               mer = val;
-                                               break;
-
-                                       case ADBC:
-                                               bc = (val == BC);
-                                               break;
-
-                                       case DOW:
-                                               tm->tm_wday = val;
-                                               break;
-
-                                       default:
-                                               return -1;
-                               }
-                               break;
-
-                       default:
-                               return -1;
-               }
-
-               if (tmask & fmask)
-                       return -1;
-               fmask |= tmask;
-       }
-
-       /* there is no year zero in AD/BC notation; i.e. "1 BC" == year 0 */
-       if (bc)
-       {
-               if (tm->tm_year > 0)
-                       tm->tm_year = -(tm->tm_year - 1);
-               else
-                       elog(ERROR, "Inconsistant use of year %04d and 'BC'", tm->tm_year);
-       }
-       else if (is2digits)
-       {
-               if (tm->tm_year < 70)
-                       tm->tm_year += 2000;
-               else if (tm->tm_year < 100)
-                       tm->tm_year += 1900;
-       }
-
-       if ((mer != HR24) && (tm->tm_hour > 12))
-               return -1;
-       if ((mer == AM) && (tm->tm_hour == 12))
-               tm->tm_hour = 0;
-       else if ((mer == PM) && (tm->tm_hour != 12))
-               tm->tm_hour += 12;
-
-       /* do additional checking for full date specs... */
-       if (*dtype == DTK_DATE)
-       {
-               if ((fmask & DTK_DATE_M) != DTK_DATE_M)
-                       return ((fmask & DTK_TIME_M) == DTK_TIME_M) ? 1 : -1;
-
-               /*
-                * check for valid day of month, now that we know for sure the
-                * month and year...
-                */
-               if ((tm->tm_mday < 1)
-                || (tm->tm_mday > day_tab[isleap(tm->tm_year)][tm->tm_mon - 1]))
-                       return -1;
-
-               /* timezone not specified? then find local timezone if possible */
-               if (((fmask & DTK_DATE_M) == DTK_DATE_M)
-                       && (tzp != NULL) && (!(fmask & DTK_M(TZ))))
-               {
-
-                       /*
-                        * daylight savings time modifier but no standard timezone?
-                        * then error
-                        */
-                       if (fmask & DTK_M(DTZMOD))
-                               return -1;
-
-                       if (IS_VALID_UTIME(tm->tm_year, tm->tm_mon, tm->tm_mday))
-                       {
-#ifdef USE_POSIX_TIME
-                               tm->tm_year -= 1900;
-                               tm->tm_mon -= 1;
-                               tm->tm_isdst = -1;
-                               mktime(tm);
-                               tm->tm_year += 1900;
-                               tm->tm_mon += 1;
-
-#if defined(HAVE_TM_ZONE)
-                               *tzp = -(tm->tm_gmtoff);                /* tm_gmtoff is
-                                                                                                * Sun/DEC-ism */
-#elif defined(HAVE_INT_TIMEZONE)
-#ifdef __CYGWIN__
-                               *tzp = ((tm->tm_isdst > 0) ? (_timezone - 3600) : _timezone);
-#else
-                               *tzp = ((tm->tm_isdst > 0) ? (timezone - 3600) : timezone);
-#endif
-#else
-#error USE_POSIX_TIME is defined but neither HAVE_TM_ZONE or HAVE_INT_TIMEZONE are defined
-#endif
-
-#else                                                  /* !USE_POSIX_TIME */
-                               *tzp = CTimeZone;
-#endif
-                       }
-                       else
-                       {
-                               tm->tm_isdst = 0;
-                               *tzp = 0;
-                       }
-               }
-       }
-
-       return 0;
-}      /* DecodeDateTime() */
-
-
-/* DecodeTimeOnly()
- * Interpret parsed string as time fields only.
- */
-int
-DecodeTimeOnly(char **field, int *ftype, int nf, int *dtype, struct tm * tm, double *fsec)
-{
-       int                     fmask,
-                               tmask,
-                               type;
-       int                     i;
-       int                     flen,
-                               val;
-       int                     is2digits = FALSE;
-       int                     mer = HR24;
-
-       *dtype = DTK_TIME;
-       tm->tm_hour = 0;
-       tm->tm_min = 0;
-       tm->tm_sec = 0;
-       tm->tm_isdst = -1;                      /* don't know daylight savings time status
-                                                                * apriori */
-       *fsec = 0;
-
-       fmask = DTK_DATE_M;
-
-       for (i = 0; i < nf; i++)
-       {
-               switch (ftype[i])
-               {
-                       case DTK_TIME:
-                               if (DecodeTime(field[i], fmask, &tmask, tm, fsec) != 0)
-                                       return -1;
-                               break;
-
-                       case DTK_NUMBER:
-                               flen = strlen(field[i]);
-
-                               if (DecodeNumberField(flen, field[i], fmask, &tmask, tm, fsec, &is2digits) != 0)
-                                       return -1;
-                               break;
-
-                       case DTK_STRING:
-                       case DTK_SPECIAL:
-                               type = DecodeSpecial(i, field[i], &val);
-                               if (type == IGNORE)
-                                       continue;
-
-                               tmask = DTK_M(type);
-                               switch (type)
-                               {
-                                       case RESERV:
-                                               switch (val)
-                                               {
-                                                       case DTK_NOW:
-                                                               tmask = DTK_TIME_M;
-                                                               *dtype = DTK_TIME;
-                                                               GetCurrentTime(tm);
-                                                               break;
-
-                                                       case DTK_ZULU:
-                                                               tmask = (DTK_TIME_M | DTK_M(TZ));
-                                                               *dtype = DTK_TIME;
-                                                               tm->tm_hour = 0;
-                                                               tm->tm_min = 0;
-                                                               tm->tm_sec = 0;
-                                                               tm->tm_isdst = 0;
-                                                               break;
-
-                                                       default:
-                                                               return -1;
-                                               }
-
-                                               break;
-
-                                       case IGNORE:
-                                               break;
-
-                                       case AMPM:
-                                               mer = val;
-                                               break;
-
-                                       default:
-                                               return -1;
-                               }
-                               break;
-
-                       default:
-                               return -1;
-               }
-
-               if (tmask & fmask)
-                       return -1;
-               fmask |= tmask;
-       }
-
-       if ((mer != HR24) && (tm->tm_hour > 12))
-               return -1;
-       if ((mer == AM) && (tm->tm_hour == 12))
-               tm->tm_hour = 0;
-       else if ((mer == PM) && (tm->tm_hour != 12))
-               tm->tm_hour += 12;
-
-       if (((tm->tm_hour < 0) || (tm->tm_hour > 23))
-               || ((tm->tm_min < 0) || (tm->tm_min > 59))
-               || ((tm->tm_sec < 0) || ((tm->tm_sec + *fsec) >= 60)))
-               return -1;
-
-       if ((fmask & DTK_TIME_M) != DTK_TIME_M)
-               return -1;
-
-       return 0;
-}      /* DecodeTimeOnly() */
-
-
-/* DecodeDate()
- * Decode date string which includes delimiters.
- * Insist on a complete set of fields.
- */
-static int
-DecodeDate(char *str, int fmask, int *tmask, struct tm * tm)
-{
-       double          fsec;
-
-       int                     nf = 0;
-       int                     i,
-                               len;
-       int                     bc = FALSE;
-       int                     is2digits = FALSE;
-       int                     type,
-                               val,
-                               dmask = 0;
-       char       *field[MAXDATEFIELDS];
-
-       /* parse this string... */
-       while ((*str != '\0') && (nf < MAXDATEFIELDS))
-       {
-               /* skip field separators */
-               while (!isalnum(*str))
-                       str++;
-
-               field[nf] = str;
-               if (isdigit(*str))
-               {
-                       while (isdigit(*str))
-                               str++;
-               }
-               else if (isalpha(*str))
-               {
-                       while (isalpha(*str))
-                               str++;
-               }
-
-               if (*str != '\0')
-                       *str++ = '\0';
-               nf++;
-       }
-
-#if 0
-       /* don't allow too many fields */
-       if (nf > 3)
-               return -1;
-#endif
-
-       *tmask = 0;
-
-       /* look first for text fields, since that will be unambiguous month */
-       for (i = 0; i < nf; i++)
-       {
-               if (isalpha(*field[i]))
-               {
-                       type = DecodeSpecial(i, field[i], &val);
-                       if (type == IGNORE)
-                               continue;
-
-                       dmask = DTK_M(type);
-                       switch (type)
-                       {
-                               case MONTH:
-                                       tm->tm_mon = val;
-                                       break;
-
-                               case ADBC:
-                                       bc = (val == BC);
-                                       break;
-
-                               default:
-                                       return -1;
-                       }
-                       if (fmask & dmask)
-                               return -1;
-
-                       fmask |= dmask;
-                       *tmask |= dmask;
-
-                       /* mark this field as being completed */
-                       field[i] = NULL;
-               }
-       }
-
-       /* now pick up remaining numeric fields */
-       for (i = 0; i < nf; i++)
-       {
-               if (field[i] == NULL)
-                       continue;
-
-               if ((len = strlen(field[i])) <= 0)
-                       return -1;
-
-               if (DecodeNumber(len, field[i], fmask, &dmask, tm, &fsec, &is2digits) != 0)
-                       return -1;
-
-               if (fmask & dmask)
-                       return -1;
-
-               fmask |= dmask;
-               *tmask |= dmask;
-       }
-
-       if ((fmask & ~(DTK_M(DOY) | DTK_M(TZ))) != DTK_DATE_M)
-               return -1;
-
-       /* there is no year zero in AD/BC notation; i.e. "1 BC" == year 0 */
-       if (bc)
-       {
-               if (tm->tm_year > 0)
-                       tm->tm_year = -(tm->tm_year - 1);
-               else
-                       elog(ERROR, "Inconsistant use of year %04d and 'BC'", tm->tm_year);
-       }
-       else if (is2digits)
-       {
-               if (tm->tm_year < 70)
-                       tm->tm_year += 2000;
-               else if (tm->tm_year < 100)
-                       tm->tm_year += 1900;
-       }
-
-       return 0;
-}      /* DecodeDate() */
-
-
-/* DecodeTime()
- * Decode time string which includes delimiters.
- * Only check the lower limit on hours, since this same code
- *     can be used to represent time spans.
- */
-static int
-DecodeTime(char *str, int fmask, int *tmask, struct tm * tm, double *fsec)
-{
-       char       *cp;
-
-       *tmask = DTK_TIME_M;
-
-       tm->tm_hour = strtol(str, &cp, 10);
-       if (*cp != ':')
-               return -1;
-       str = cp + 1;
-       tm->tm_min = strtol(str, &cp, 10);
-       if (*cp == '\0')
-       {
-               tm->tm_sec = 0;
-               *fsec = 0;
-
-       }
-       else if (*cp != ':')
-       {
-               return -1;
-
-       }
-       else
-       {
-               str = cp + 1;
-               tm->tm_sec = strtol(str, &cp, 10);
-               if (*cp == '\0')
-                       *fsec = 0;
-               else if (*cp == '.')
-               {
-                       str = cp;
-                       *fsec = strtod(str, &cp);
-                       if (cp == str)
-                               return -1;
-               }
-               else
-                       return -1;
-       }
-
-       /* do a sanity check */
-       if ((tm->tm_hour < 0)
-               || (tm->tm_min < 0) || (tm->tm_min > 59)
-               || (tm->tm_sec < 0) || (tm->tm_sec > 59))
-               return -1;
-
-       return 0;
-}      /* DecodeTime() */
-
-
-/* DecodeNumber()
- * Interpret numeric field as a date value in context.
- */
-static int
-DecodeNumber(int flen, char *str, int fmask,
-                        int *tmask, struct tm * tm, double *fsec, int *is2digits)
-{
-       int                     val;
-       char       *cp;
-
-       *tmask = 0;
-
-       val = strtol(str, &cp, 10);
-       if (cp == str)
-               return -1;
-       if (*cp == '.')
-       {
-               *fsec = strtod(cp, &cp);
-               if (*cp != '\0')
-                       return -1;
-       }
-
-       /* Special case day of year? */
-       if ((flen == 3) && (fmask & DTK_M(YEAR))
-               && ((val >= 1) && (val <= 366)))
-       {
-               *tmask = (DTK_M(DOY) | DTK_M(MONTH) | DTK_M(DAY));
-               tm->tm_yday = val;
-               j2date((date2j(tm->tm_year, 1, 1) + tm->tm_yday - 1),
-                          &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
-
-       }
-
-       /*
-        * Enough digits to be unequivocal year? Used to test for 4 digits or
-        * more, but we now test first for a three-digit doy so anything
-        * bigger than two digits had better be an explicit year. - thomas
-        * 1999-01-09
-        */
-       else if (flen > 2)
-       {
-               *tmask = DTK_M(YEAR);
-
-               /* already have a year? then see if we can substitute... */
-               if ((fmask & DTK_M(YEAR)) && (!(fmask & DTK_M(DAY)))
-                       && ((tm->tm_year >= 1) && (tm->tm_year <= 31)))
-               {
-                       tm->tm_mday = tm->tm_year;
-                       *tmask = DTK_M(DAY);
-               }
-
-               tm->tm_year = val;
-       }
-       /* already have year? then could be month */
-       else if ((fmask & DTK_M(YEAR)) && (!(fmask & DTK_M(MONTH)))
-                        && ((val >= 1) && (val <= 12)))
-       {
-               *tmask = DTK_M(MONTH);
-               tm->tm_mon = val;
-               /* no year and EuroDates enabled? then could be day */
-       }
-       else if ((EuroDates || (fmask & DTK_M(MONTH)))
-                        && (!(fmask & DTK_M(YEAR)) && !(fmask & DTK_M(DAY)))
-                        && ((val >= 1) && (val <= 31)))
-       {
-               *tmask = DTK_M(DAY);
-               tm->tm_mday = val;
-       }
-       else if ((!(fmask & DTK_M(MONTH)))
-                        && ((val >= 1) && (val <= 12)))
-       {
-               *tmask = DTK_M(MONTH);
-               tm->tm_mon = val;
-       }
-       else if ((!(fmask & DTK_M(DAY)))
-                        && ((val >= 1) && (val <= 31)))
-       {
-               *tmask = DTK_M(DAY);
-               tm->tm_mday = val;
-       }
-       else if (!(fmask & DTK_M(YEAR)))
-       {
-               *tmask = DTK_M(YEAR);
-               tm->tm_year = val;
-
-               /* adjust ONLY if exactly two digits... */
-               *is2digits = (flen == 2);
-       }
-       else
-               return -1;
-
-       return 0;
-}      /* DecodeNumber() */
-
-
-/* DecodeNumberField()
- * Interpret numeric string as a concatenated date field.
- */
-static int
-DecodeNumberField(int len, char *str, int fmask,
-                               int *tmask, struct tm * tm, double *fsec, int *is2digits)
-{
-       char       *cp;
-
-       /* yyyymmdd? */
-       if (len == 8)
-       {
-               *tmask = DTK_DATE_M;
-
-               tm->tm_mday = atoi(str + 6);
-               *(str + 6) = '\0';
-               tm->tm_mon = atoi(str + 4);
-               *(str + 4) = '\0';
-               tm->tm_year = atoi(str + 0);
-               /* yymmdd or hhmmss? */
-       }
-       else if (len == 6)
-       {
-               if (fmask & DTK_DATE_M)
-               {
-                       *tmask = DTK_TIME_M;
-                       tm->tm_sec = atoi(str + 4);
-                       *(str + 4) = '\0';
-                       tm->tm_min = atoi(str + 2);
-                       *(str + 2) = '\0';
-                       tm->tm_hour = atoi(str + 0);
-               }
-               else
-               {
-                       *tmask = DTK_DATE_M;
-                       tm->tm_mday = atoi(str + 4);
-                       *(str + 4) = '\0';
-                       tm->tm_mon = atoi(str + 2);
-                       *(str + 2) = '\0';
-                       tm->tm_year = atoi(str + 0);
-                       *is2digits = TRUE;
-               }
-
-       }
-       else if ((len == 5) && !(fmask & DTK_DATE_M))
-       {
-               *tmask = DTK_DATE_M;
-               tm->tm_mday = atoi(str + 2);
-               *(str + 2) = '\0';
-               tm->tm_mon = 1;
-               tm->tm_year = atoi(str + 0);
-               *is2digits = TRUE;
-       }
-       else if (strchr(str, '.') != NULL)
-       {
-               *tmask = DTK_TIME_M;
-               tm->tm_sec = strtod((str + 4), &cp);
-               if (cp == (str + 4))
-                       return -1;
-               if (*cp == '.')
-                       *fsec = strtod(cp, NULL);
-               *(str + 4) = '\0';
-               tm->tm_min = strtod((str + 2), &cp);
-               *(str + 2) = '\0';
-               tm->tm_hour = strtod((str + 0), &cp);
-
-       }
-       else
-               return -1;
-
-       return 0;
-}      /* DecodeNumberField() */
-
-
-/* DecodeTimezone()
- * Interpret string as a numeric timezone.
- */
-static int
-DecodeTimezone(char *str, int *tzp)
-{
-       int                     tz;
-       int                     hr,
-                               min;
-       char       *cp;
-       int                     len;
-
-       /* assume leading character is "+" or "-" */
-       hr = strtol((str + 1), &cp, 10);
-
-       /* explicit delimiter? */
-       if (*cp == ':')
-       {
-               min = strtol((cp + 1), &cp, 10);
-
-               /* otherwise, might have run things together... */
-       }
-       else if ((*cp == '\0') && ((len = strlen(str)) > 3))
-       {
-               min = strtol((str + len - 2), &cp, 10);
-               *(str + len - 2) = '\0';
-               hr = strtol((str + 1), &cp, 10);
-
-       }
-       else
-               min = 0;
-
-       tz = (hr * 60 + min) * 60;
-       if (*str == '-')
-               tz = -tz;
-
-       *tzp = -tz;
-       return *cp != '\0';
-}      /* DecodeTimezone() */
-
-
-/* DecodeSpecial()
- * Decode text string using lookup table.
- * Implement a cache lookup since it is likely that dates
- *     will be related in format.
- */
-static int
-DecodeSpecial(int field, char *lowtoken, int *val)
-{
-       int                     type;
-       datetkn    *tp;
-
-#if USE_DATE_CACHE
-       if ((datecache[field] != NULL)
-               && (strncmp(lowtoken, datecache[field]->token, TOKMAXLEN) == 0))
-               tp = datecache[field];
-       else
-       {
-#endif
-               tp = datebsearch(lowtoken, datetktbl, szdatetktbl);
-#if USE_DATE_CACHE
-       }
-       datecache[field] = tp;
-#endif
-       if (tp == NULL)
-       {
-               type = IGNORE;
-               *val = 0;
-       }
-       else
-       {
-               type = tp->type;
-               switch (type)
-               {
-                       case TZ:
-                       case DTZ:
-                       case DTZMOD:
-                               *val = FROMVAL(tp);
-                               break;
-
-                       default:
-                               *val = tp->value;
-                               break;
-               }
-       }
-
-       return type;
-}      /* DecodeSpecial() */
-
-
-/* DecodeDateDelta()
- * Interpret previously parsed fields for general time interval.
- * Return 0 if decoded and -1 if problems.
- *
- * Allow "date" field DTK_DATE since this could be just
- *     an unsigned floating point number. - thomas 1997-11-16
- *
- * Allow ISO-style time span, with implicit units on number of days
- *     preceeding an hh:mm:ss field. - thomas 1998-04-30
- */
-int
-DecodeDateDelta(char **field, int *ftype, int nf, int *dtype, struct tm * tm, double *fsec)
-{
-       int                     is_before = FALSE;
-
-       char       *cp;
-       int                     fmask = 0,
-                               tmask,
-                               type;
-       int                     i;
-       int                     flen,
-                               val;
-       double          fval;
-       double          sec;
-
-       *dtype = DTK_DELTA;
-
-       type = DTK_SECOND;
-       tm->tm_year = 0;
-       tm->tm_mon = 0;
-       tm->tm_mday = 0;
-       tm->tm_hour = 0;
-       tm->tm_min = 0;
-       tm->tm_sec = 0;
-       *fsec = 0;
-
-       /* read through list backwards to pick up units before values */
-       for (i = nf - 1; i >= 0; i--)
-       {
-               switch (ftype[i])
-               {
-                       case DTK_TIME:
-                               if (DecodeTime(field[i], fmask, &tmask, tm, fsec) != 0)
-                                       return -1;
-                               type = DTK_DAY;
-                               break;
-
-                       case DTK_TZ:
-
-                               /*
-                                * Timezone is a token with a leading sign character and
-                                * otherwise the same as a non-signed numeric field
-                                */
-                       case DTK_DATE:
-                       case DTK_NUMBER:
-                               val = strtol(field[i], &cp, 10);
-                               if (*cp == '.')
-                               {
-                                       fval = strtod(cp, &cp);
-                                       if (*cp != '\0')
-                                               return -1;
-
-                                       if (val < 0)
-                                               fval = -(fval);
-                               }
-                               else if (*cp == '\0')
-                                       fval = 0;
-                               else
-                                       return -1;
-
-                               flen = strlen(field[i]);
-                               tmask = 0;              /* DTK_M(type); */
-
-                               switch (type)
-                               {
-                                       case DTK_MICROSEC:
-                                               *fsec += ((val + fval) * 1e-6);
-                                               break;
-
-                                       case DTK_MILLISEC:
-                                               *fsec += ((val + fval) * 1e-3);
-                                               break;
-
-                                       case DTK_SECOND:
-                                               tm->tm_sec += val;
-                                               *fsec += fval;
-                                               tmask = DTK_M(SECOND);
-                                               break;
-
-                                       case DTK_MINUTE:
-                                               tm->tm_min += val;
-                                               if (fval != 0)
-                                                       tm->tm_sec += (fval * 60);
-                                               tmask = DTK_M(MINUTE);
-                                               break;
-
-                                       case DTK_HOUR:
-                                               tm->tm_hour += val;
-                                               if (fval != 0)
-                                                       tm->tm_sec += (fval * 3600);
-                                               tmask = DTK_M(HOUR);
-                                               break;
-
-                                       case DTK_DAY:
-                                               tm->tm_mday += val;
-                                               if (fval != 0)
-                                                       tm->tm_sec += (fval * 86400);
-                                               tmask = ((fmask & DTK_M(DAY)) ? 0 : DTK_M(DAY));
-                                               break;
-
-                                       case DTK_WEEK:
-                                               tm->tm_mday += val * 7;
-                                               if (fval != 0)
-                                                       tm->tm_sec += (fval * (7 * 86400));
-                                               tmask = ((fmask & DTK_M(DAY)) ? 0 : DTK_M(DAY));
-                                               break;
-
-                                       case DTK_MONTH:
-                                               tm->tm_mon += val;
-                                               if (fval != 0)
-                                                       tm->tm_sec += (fval * (30 * 86400));
-                                               tmask = DTK_M(MONTH);
-                                               break;
-
-                                       case DTK_YEAR:
-                                               tm->tm_year += val;
-                                               if (fval != 0)
-                                                       tm->tm_mon += (fval * 12);
-                                               tmask = ((fmask & DTK_M(YEAR)) ? 0 : DTK_M(YEAR));
-                                               break;
-
-                                       case DTK_DECADE:
-                                               tm->tm_year += val * 10;
-                                               if (fval != 0)
-                                                       tm->tm_mon += (fval * 120);
-                                               tmask = ((fmask & DTK_M(YEAR)) ? 0 : DTK_M(YEAR));
-                                               break;
-
-                                       case DTK_CENTURY:
-                                               tm->tm_year += val * 100;
-                                               if (fval != 0)
-                                                       tm->tm_mon += (fval * 1200);
-                                               tmask = ((fmask & DTK_M(YEAR)) ? 0 : DTK_M(YEAR));
-                                               break;
-
-                                       case DTK_MILLENIUM:
-                                               tm->tm_year += val * 1000;
-                                               if (fval != 0)
-                                                       tm->tm_mon += (fval * 12000);
-                                               tmask = ((fmask & DTK_M(YEAR)) ? 0 : DTK_M(YEAR));
-                                               break;
-
-                                       default:
-                                               return -1;
-                               }
-                               break;
-
-                       case DTK_STRING:
-                       case DTK_SPECIAL:
-                               type = DecodeUnits(i, field[i], &val);
-                               if (type == IGNORE)
-                                       continue;
-
-                               tmask = 0;              /* DTK_M(type); */
-                               switch (type)
-                               {
-                                       case UNITS:
-                                               type = val;
-                                               break;
-
-                                       case AGO:
-                                               is_before = TRUE;
-                                               type = val;
-                                               break;
-
-                                       case RESERV:
-                                               tmask = (DTK_DATE_M || DTK_TIME_M);
-                                               *dtype = val;
-                                               break;
-
-                                       default:
-                                               return -1;
-                               }
-                               break;
-
-                       default:
-                               return -1;
-               }
-
-               if (tmask & fmask)
-                       return -1;
-               fmask |= tmask;
-       }
-
-       if (*fsec != 0)
-       {
-               TMODULO(*fsec, sec, 1e0);
-               tm->tm_sec += sec;
-       }
-
-       if (is_before)
-       {
-               *fsec = -(*fsec);
-               tm->tm_sec = -(tm->tm_sec);
-               tm->tm_min = -(tm->tm_min);
-               tm->tm_hour = -(tm->tm_hour);
-               tm->tm_mday = -(tm->tm_mday);
-               tm->tm_mon = -(tm->tm_mon);
-               tm->tm_year = -(tm->tm_year);
-       }
-
-       /* ensure that at least one time field has been found */
-       return (fmask != 0) ? 0 : -1;
-}      /* DecodeDateDelta() */
-
-
-/* DecodeUnits()
- * Decode text string using lookup table.
- * This routine supports time interval decoding.
- */
-static int
-DecodeUnits(int field, char *lowtoken, int *val)
-{
-       int                     type;
-       datetkn    *tp;
-
-#if USE_DATE_CACHE
-       if ((deltacache[field] != NULL)
-               && (strncmp(lowtoken, deltacache[field]->token, TOKMAXLEN) == 0))
-               tp = deltacache[field];
-       else
-       {
-#endif
-               tp = datebsearch(lowtoken, deltatktbl, szdeltatktbl);
-#if USE_DATE_CACHE
-       }
-       deltacache[field] = tp;
-#endif
-       if (tp == NULL)
-       {
-               type = IGNORE;
-               *val = 0;
-       }
-       else
-       {
-               type = tp->type;
-               if ((type == TZ) || (type == DTZ))
-                       *val = FROMVAL(tp);
-               else
-                       *val = tp->value;
-       }
-
-       return type;
-}      /* DecodeUnits() */
-
-
-/* datebsearch()
- * Binary search -- from Knuth (6.2.1) Algorithm B.  Special case like this
- * is WAY faster than the generic bsearch().
- */
-static datetkn *
-datebsearch(char *key, datetkn *base, unsigned int nel)
-{
-       datetkn    *last = base + nel - 1,
-                          *position;
-       int                     result;
-
-       while (last >= base)
-       {
-               position = base + ((last - base) >> 1);
-               result = key[0] - position->token[0];
-               if (result == 0)
-               {
-                       result = strncmp(key, position->token, TOKMAXLEN);
-                       if (result == 0)
-                               return position;
-               }
-               if (result < 0)
-                       last = position - 1;
-               else
-                       base = position + 1;
-       }
-       return NULL;
-}
-
-
-/* EncodeSpecialDateTime()
- * Convert reserved datetime data type to string.
- */
-static int
-EncodeSpecialDateTime(DateTime dt, char *str)
-{
-       if (DATETIME_IS_RESERVED(dt))
-       {
-               if (DATETIME_IS_INVALID(dt))
-                       strcpy(str, INVALID);
-               else if (DATETIME_IS_NOBEGIN(dt))
-                       strcpy(str, EARLY);
-               else if (DATETIME_IS_NOEND(dt))
-                       strcpy(str, LATE);
-               else if (DATETIME_IS_CURRENT(dt))
-                       strcpy(str, DCURRENT);
-               else if (DATETIME_IS_EPOCH(dt))
-                       strcpy(str, EPOCH);
-               else
-                       strcpy(str, INVALID);
-               return TRUE;
-       }
-
-       return FALSE;
-}      /* EncodeSpecialDateTime() */
-
-
-/* EncodeDateOnly()
- * Encode date as local time.
- */
-int
-EncodeDateOnly(struct tm * tm, int style, char *str)
-{
-       if ((tm->tm_mon < 1) || (tm->tm_mon > 12))
-               return -1;
-
-       switch (style)
-       {
-                       /* compatible with ISO date formats */
-               case USE_ISO_DATES:
-                       if (tm->tm_year > 0)
-                               sprintf(str, "%04d-%02d-%02d",
-                                               tm->tm_year, tm->tm_mon, tm->tm_mday);
-                       else
-                               sprintf(str, "%04d-%02d-%02d %s",
-                                         -(tm->tm_year - 1), tm->tm_mon, tm->tm_mday, "BC");
-                       break;
-
-                       /* compatible with Oracle/Ingres date formats */
-               case USE_SQL_DATES:
-                       if (EuroDates)
-                               sprintf(str, "%02d/%02d", tm->tm_mday, tm->tm_mon);
-                       else
-                               sprintf(str, "%02d/%02d", tm->tm_mon, tm->tm_mday);
-                       if (tm->tm_year > 0)
-                               sprintf((str + 5), "/%04d", tm->tm_year);
-                       else
-                               sprintf((str + 5), "/%04d %s", -(tm->tm_year - 1), "BC");
-                       break;
-
-                       /* German-style date format */
-               case USE_GERMAN_DATES:
-                       sprintf(str, "%02d.%02d", tm->tm_mday, tm->tm_mon);
-                       if (tm->tm_year > 0)
-                               sprintf((str + 5), ".%04d", tm->tm_year);
-                       else
-                               sprintf((str + 5), ".%04d %s", -(tm->tm_year - 1), "BC");
-                       break;
-
-                       /* traditional date-only style for Postgres */
-               case USE_POSTGRES_DATES:
-               default:
-                       if (EuroDates)
-                               sprintf(str, "%02d-%02d", tm->tm_mday, tm->tm_mon);
-                       else
-                               sprintf(str, "%02d-%02d", tm->tm_mon, tm->tm_mday);
-                       if (tm->tm_year > 0)
-                               sprintf((str + 5), "-%04d", tm->tm_year);
-                       else
-                               sprintf((str + 5), "-%04d %s", -(tm->tm_year - 1), "BC");
-                       break;
-       }
-
-       return TRUE;
-}      /* EncodeDateOnly() */
-
-
-/* EncodeTimeOnly()
- * Encode time fields only.
- */
-int
-EncodeTimeOnly(struct tm * tm, double fsec, int style, char *str)
-{
-       double          sec;
-
-       if ((tm->tm_hour < 0) || (tm->tm_hour > 24))
-               return -1;
-
-       sec = (tm->tm_sec + fsec);
-
-       sprintf(str, "%02d:%02d:", tm->tm_hour, tm->tm_min);
-       sprintf((str + 6), ((fsec != 0) ? "%05.2f" : "%02.0f"), sec);
-
-       return TRUE;
-}      /* EncodeTimeOnly() */
-
-
-/* EncodeDateTime()
- * Encode date and time interpreted as local time.
- * Support several date styles:
- *     Postgres - day mon hh:mm:ss yyyy tz
- *     SQL - mm/dd/yyyy hh:mm:ss.ss tz
- *     ISO - yyyy-mm-dd hh:mm:ss+/-tz
- *     German - dd.mm/yyyy hh:mm:ss tz
- * Variants (affects order of month and day for Postgres and SQL styles):
- *     US - mm/dd/yyyy
- *     European - dd/mm/yyyy
- */
-int
-EncodeDateTime(struct tm * tm, double fsec, int *tzp, char **tzn, int style, char *str)
-{
-       int                     day,
-                               hour,
-                               min;
-       double          sec;
-
-       if ((tm->tm_mon < 1) || (tm->tm_mon > 12))
-               return -1;
-
-       sec = (tm->tm_sec + fsec);
-
-       switch (style)
-       {
-                       /* compatible with ISO date formats */
-
-               case USE_ISO_DATES:
-                       if (tm->tm_year > 0)
-                       {
-                               sprintf(str, "%04d-%02d-%02d %02d:%02d:",
-                                               tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min);
-                               sprintf((str + 17), ((fsec != 0) ? "%05.2f" : "%02.0f"), sec);
-
-                               if ((*tzn != NULL) && (tm->tm_isdst >= 0))
-                               {
-                                       if (tzp != NULL)
-                                       {
-                                               hour = -(*tzp / 3600);
-                                               min = ((abs(*tzp) / 60) % 60);
-                                       }
-                                       else
-                                       {
-                                               hour = 0;
-                                               min = 0;
-                                       }
-                                       sprintf((str + strlen(str)), ((min != 0) ? "%+03d:%02d" : "%+03d"), hour, min);
-                               }
-
-                       }
-                       else
-                       {
-                               if (tm->tm_hour || tm->tm_min)
-                                       sprintf(str, "%04d-%02d-%02d %02d:%02d %s",
-                                                       -(tm->tm_year - 1), tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, "BC");
-                               else
-                                       sprintf(str, "%04d-%02d-%02d %s",
-                                         -(tm->tm_year - 1), tm->tm_mon, tm->tm_mday, "BC");
-                       }
-                       break;
-
-                       /* compatible with Oracle/Ingres date formats */
-               case USE_SQL_DATES:
-                       if (EuroDates)
-                               sprintf(str, "%02d/%02d", tm->tm_mday, tm->tm_mon);
-                       else
-                               sprintf(str, "%02d/%02d", tm->tm_mon, tm->tm_mday);
-
-                       if (tm->tm_year > 0)
-                       {
-                               sprintf((str + 5), "/%04d %02d:%02d:%05.2f",
-                                               tm->tm_year, tm->tm_hour, tm->tm_min, sec);
-
-                               if ((*tzn != NULL) && (tm->tm_isdst >= 0))
-                               {
-                                       strcpy((str + 22), " ");
-                                       strcpy((str + 23), *tzn);
-                               }
-
-                       }
-                       else
-                               sprintf((str + 5), "/%04d %02d:%02d %s",
-                                         -(tm->tm_year - 1), tm->tm_hour, tm->tm_min, "BC");
-                       break;
-
-                       /* German variant on European style */
-               case USE_GERMAN_DATES:
-                       sprintf(str, "%02d.%02d", tm->tm_mday, tm->tm_mon);
-                       if (tm->tm_year > 0)
-                       {
-                               sprintf((str + 5), ".%04d %02d:%02d:%05.2f",
-                                               tm->tm_year, tm->tm_hour, tm->tm_min, sec);
-
-                               if ((*tzn != NULL) && (tm->tm_isdst >= 0))
-                               {
-                                       strcpy((str + 22), " ");
-                                       strcpy((str + 23), *tzn);
-                               }
-
-                       }
-                       else
-                               sprintf((str + 5), ".%04d %02d:%02d %s",
-                                         -(tm->tm_year - 1), tm->tm_hour, tm->tm_min, "BC");
-                       break;
-
-                       /* backward-compatible with traditional Postgres abstime dates */
-               case USE_POSTGRES_DATES:
-               default:
-                       day = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday);
-                       tm->tm_wday = j2day(day);
-
-                       strncpy(str, days[tm->tm_wday], 3);
-                       strcpy((str + 3), " ");
-
-                       if (EuroDates)
-                               sprintf((str + 4), "%02d %3s", tm->tm_mday, months[tm->tm_mon - 1]);
-                       else
-                               sprintf((str + 4), "%3s %02d", months[tm->tm_mon - 1], tm->tm_mday);
-
-                       if (tm->tm_year > 0)
-                       {
-                               sprintf((str + 10), " %02d:%02d", tm->tm_hour, tm->tm_min);
-                               if (fsec != 0)
-                               {
-                                       sprintf((str + 16), ":%05.2f %04d", sec, tm->tm_year);
-                                       if ((*tzn != NULL) && (tm->tm_isdst >= 0))
-                                       {
-                                               strcpy((str + 27), " ");
-                                               strncpy((str + 28), *tzn, MAXTZLEN);
-                                       }
-                               }
-                               else
-                               {
-                                       sprintf((str + 16), ":%02.0f %04d", sec, tm->tm_year);
-                                       if ((*tzn != NULL) && (tm->tm_isdst >= 0))
-                                       {
-                                               strcpy((str + 24), " ");
-                                               strncpy((str + 25), *tzn, MAXTZLEN);
-                                       }
-                               }
-
-                       }
-                       else
-                       {
-                               sprintf((str + 10), " %02d:%02d %04d %s",
-                                         tm->tm_hour, tm->tm_min, -(tm->tm_year - 1), "BC");
-                       }
-                       break;
-       }
-
-       return TRUE;
-}      /* EncodeDateTime() */
-
-
-/* EncodeTimeSpan()
- * Interpret time structure as a delta time and convert to string.
- *
- * Support "traditional Postgres" and ISO-8601 styles.
- * Actually, afaik ISO does not address time interval formatting,
- *     but this looks similar to the spec for absolute date/time.
- * - thomas 1998-04-30
- */
-int
-EncodeTimeSpan(struct tm * tm, double fsec, int style, char *str)
-{
-       int                     is_before = FALSE;
-       int                     is_nonzero = FALSE;
-       char       *cp = str;
-
-       switch (style)
-       {
-                       /* compatible with ISO date formats */
-               case USE_ISO_DATES:
-                       break;
-
-               default:
-                       strcpy(cp, "@ ");
-                       cp += strlen(cp);
-                       break;
-       }
-
-       if (tm->tm_year != 0)
-       {
-               is_before |= (tm->tm_year < 0);
-               sprintf(cp, "%d year%s",
-                               abs(tm->tm_year), ((abs(tm->tm_year) != 1) ? "s" : ""));
-               cp += strlen(cp);
-               is_nonzero = TRUE;
-       }
-
-       if (tm->tm_mon != 0)
-       {
-               is_before |= (tm->tm_mon < 0);
-               sprintf(cp, "%s%d mon%s", (is_nonzero ? " " : ""),
-                               abs(tm->tm_mon), ((abs(tm->tm_mon) != 1) ? "s" : ""));
-               cp += strlen(cp);
-               is_nonzero = TRUE;
-       }
-
-       switch (style)
-       {
-                       /* compatible with ISO date formats */
-               case USE_ISO_DATES:
-                       if (tm->tm_mday != 0)
-                       {
-                               is_before |= (tm->tm_mday < 0);
-                               sprintf(cp, "%s%d", (is_nonzero ? " " : ""), abs(tm->tm_mday));
-                               cp += strlen(cp);
-                               is_nonzero = TRUE;
-                       }
-                       is_before |= ((tm->tm_hour < 0) || (tm->tm_min < 0));
-                       sprintf(cp, "%s%02d:%02d", (is_nonzero ? " " : ""),
-                                       abs(tm->tm_hour), abs(tm->tm_min));
-                       cp += strlen(cp);
-                       if ((tm->tm_hour != 0) || (tm->tm_min != 0))
-                               is_nonzero = TRUE;
-
-                       /* fractional seconds? */
-                       if (fsec != 0)
-                       {
-                               fsec += tm->tm_sec;
-                               is_before |= (fsec < 0);
-                               sprintf(cp, ":%05.2f", fabs(fsec));
-                               cp += strlen(cp);
-                               is_nonzero = TRUE;
-
-                               /* otherwise, integer seconds only? */
-                       }
-                       else if (tm->tm_sec != 0)
-                       {
-                               is_before |= (tm->tm_sec < 0);
-                               sprintf(cp, ":%02d", abs(tm->tm_sec));
-                               cp += strlen(cp);
-                               is_nonzero = TRUE;
-                       }
-                       break;
-
-               case USE_POSTGRES_DATES:
-               default:
-                       if (tm->tm_mday != 0)
-                       {
-                               is_before |= (tm->tm_mday < 0);
-                               sprintf(cp, "%s%d day%s", (is_nonzero ? " " : ""),
-                                abs(tm->tm_mday), ((abs(tm->tm_mday) != 1) ? "s" : ""));
-                               cp += strlen(cp);
-                               is_nonzero = TRUE;
-                       }
-                       if (tm->tm_hour != 0)
-                       {
-                               is_before |= (tm->tm_hour < 0);
-                               sprintf(cp, "%s%d hour%s", (is_nonzero ? " " : ""),
-                                abs(tm->tm_hour), ((abs(tm->tm_hour) != 1) ? "s" : ""));
-                               cp += strlen(cp);
-                               is_nonzero = TRUE;
-                       }
-
-                       if (tm->tm_min != 0)
-                       {
-                               is_before |= (tm->tm_min < 0);
-                               sprintf(cp, "%s%d min%s", (is_nonzero ? " " : ""),
-                                  abs(tm->tm_min), ((abs(tm->tm_min) != 1) ? "s" : ""));
-                               cp += strlen(cp);
-                               is_nonzero = TRUE;
-                       }
-
-                       /* fractional seconds? */
-                       if (fsec != 0)
-                       {
-                               fsec += tm->tm_sec;
-                               is_before |= (fsec < 0);
-                               sprintf(cp, "%s%.2f secs", (is_nonzero ? " " : ""), fabs(fsec));
-                               cp += strlen(cp);
-                               is_nonzero = TRUE;
-
-                               /* otherwise, integer seconds only? */
-                       }
-                       else if (tm->tm_sec != 0)
-                       {
-                               is_before |= (tm->tm_sec < 0);
-                               sprintf(cp, "%s%d sec%s", (is_nonzero ? " " : ""),
-                                  abs(tm->tm_sec), ((abs(tm->tm_sec) != 1) ? "s" : ""));
-                               cp += strlen(cp);
-                               is_nonzero = TRUE;
-                       }
-                       break;
-       }
-
-       /* identically zero? then put in a unitless zero... */
-       if (!is_nonzero)
-       {
-               strcat(cp, "0");
-               cp += strlen(cp);
-       }
-
-       if (is_before)
-       {
-               strcat(cp, " ago");
-               cp += strlen(cp);
-       }
-
-       return 0;
-}      /* EncodeTimeSpan() */
-
-
-#if defined(linux) && defined(__powerpc__)
-int
-datetime_is_epoch(double j)
-{
-       static union
-       {
-               double          epoch;
-               unsigned char c[8];
-       }                       u;
-
-       u.c[0] = 0x80;                          /* sign bit */
-       u.c[1] = 0x10;                          /* DBL_MIN */
-
-       return j == u.epoch;
-}
-int
-datetime_is_current(double j)
-{
-       static union
-       {
-               double          current;
-               unsigned char c[8];
-       }                       u;
-
-       u.c[1] = 0x10;                          /* DBL_MIN */
-
-       return j == u.current;
-}
-
-#endif
index e8f6d2cd4772e126517ef812e1aad2064ed46169..7281d4f4dcea581acd779c63b366a4e990109bf2 100644 (file)
@@ -1,45 +1,45 @@
 /* -----------------------------------------------------------------------
  * formatting.c
  *
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/formatting.c,v 1.3 2000/02/08 15:56:55 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/formatting.c,v 1.4 2000/02/16 17:24:48 thomas Exp $
  *
  *
  *   Portions Copyright (c) 1999-2000, PostgreSQL, Inc
  *
  *
- *   TO_CHAR(); TO_DATETIME(); TO_DATE(); TO_NUMBER();  
+ *   TO_CHAR(); TO_TIMESTAMP(); TO_DATE(); TO_NUMBER();  
  *
- *   The PostgreSQL routines for a DateTime/int/float/numeric formatting, 
+ *   The PostgreSQL routines for a timestamp/int/float/numeric formatting, 
  *   inspire with Oracle TO_CHAR() / TO_DATE() / TO_NUMBER() routines.  
  *
  *
  *   Cache & Memory:
  *     Routines use (itself) internal cache for format pictures. If 
- *     new format arg is same as a last format string, routines not 
+ *     new format arg is same as a last format string, routines do not 
  *     call the format-parser. 
  *     
- *     The cache use static buffer and is persistent across transactions. If
- *     format-picture is bigger than cache buffer, parser is called always. 
+ *     The cache uses a static buffer and is persistent across transactions.
+ *     If format-picture is bigger than cache buffer, parser is called always. 
  *
  *   NOTE for Number version:
  *     All in this version is implemented as keywords ( => not used
  *     suffixes), because a format picture is for *one* item (number) 
- *     only. It not is as a datetime version, where each keyword (can) 
+ *     only. It not is as a timestamp version, where each keyword (can) 
  *     has suffix.  
  *
- *   NOTE for DateTime version:
- *     In this modul is *not* used POSIX 'struct tm' type, but 
+ *   NOTE for Timestamp routines:
+ *     In this module the POSIX 'struct tm' type is *not* used, but rather
  *     PgSQL type, which has tm_mon based on one (*non* zero) and
  *     year *not* based on 1900, but is used full year number.  
- *     Modul support AC / BC years.     
+ *     Module supports AC / BC years.
  *
  *  Supported types for to_char():
  *             
- *             Timestamp, DateTime, Numeric, int4, int8, float4, float8
+ *             Timestamp, Numeric, int4, int8, float4, float8
  *
  *  Supported types for reverse conversion:
  *
- *             Datetime        - to_datetime()
+ *             Timestamp       - to_timestamp()
  *             Date            - to_date()
  *             Numeric         - to_number()           
  *  
 #define MAXDOUBLEWIDTH  128
 
 /* ----------
- * External (defined in PgSQL dt.c (datetime utils)) 
+ * External (defined in PgSQL dt.c (timestamp utils)) 
  * ----------
  */
 extern  char           *months[],      /* month abbreviation   */
@@ -1377,14 +1377,14 @@ dch_time(int arg, char *inout, int suf, int flag, FormatNode *node)
                                str_numth(p_inout, inout, S_TH_TYPE(suf));
                        return strlen(p_inout)-1;               
                }  else if (flag == FROM_CHAR) 
-                       elog(ERROR, "to_datatime()/to_timestamp(): SSSS is not supported");
+                       elog(ERROR, "to_datatime(): SSSS is not supported");
        }       
        return -1;      
 }
 
 #define CHECK_SEQ_SEARCH(_l, _s) {                                     \
        if (_l <= 0) {                                                  \
-               elog(ERROR, "to_datatime()/to_timestamp(): bad value for %s", _s);              \
+               elog(ERROR, "to_datatime(): bad value for %s", _s);             \
        }                                                               \
 }
 
@@ -1600,7 +1600,7 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node)
                                return 1;
                        
                }  else if (flag == FROM_CHAR)
-                       elog(ERROR, "to_datatime()/to_timestamp(): WW is not supported");
+                       elog(ERROR, "to_datatime(): WW is not supported");
        case DCH_Q:
                if (flag == TO_CHAR) {
                        sprintf(inout, "%d", (tm->tm_mon-1)/3+1);               
@@ -1611,7 +1611,7 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node)
                        return 0;
                        
                } else if (flag == FROM_CHAR)
-                       elog(ERROR, "to_datatime()/to_timestamp(): Q is not supported");
+                       elog(ERROR, "to_datatime(): Q is not supported");
                        
        case DCH_CC:
                if (flag == TO_CHAR) {
@@ -1625,7 +1625,7 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node)
                        return strlen(p_inout)-1;
                        
                } else if (flag == FROM_CHAR)
-                       elog(ERROR, "to_datatime()/to_timestamp(): CC is not supported");
+                       elog(ERROR, "to_datatime(): CC is not supported");
        case DCH_Y_YYY: 
                if (flag == TO_CHAR) {
                        i= YEAR_ABS(tm->tm_year) / 1000;
@@ -1764,7 +1764,7 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node)
                        return 0;
                        
                } else if (flag == FROM_CHAR)
-                       elog(ERROR, "to_datatime()/to_timestamp(): W is not supported");
+                       elog(ERROR, "to_datatime(): W is not supported");
                        
        case DCH_J:
                if (flag == TO_CHAR) {
@@ -1773,7 +1773,7 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node)
                                str_numth(p_inout, inout, S_TH_TYPE(suf));
                        return strlen(p_inout)-1;
                } else if (flag == FROM_CHAR)
-                       elog(ERROR, "to_datatime()/to_timestamp(): J is not supported");        
+                       elog(ERROR, "to_datatime(): J is not supported");       
        }       
        return -1;      
 }
@@ -1783,11 +1783,11 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node)
  ***************************************************************************/
 
 /* -------------------
- * DATETIME to_char()
+ * TIMESTAMP to_char()
  * -------------------
  */
 text *
-datetime_to_char(DateTime *dt, text *fmt)
+timestamp_to_char(Timestamp *dt, text *fmt)
 {
        static FormatNode       CacheFormat[ DCH_CACHE_SIZE +1];
        static char             CacheStr[ DCH_CACHE_SIZE +1];
@@ -1814,14 +1814,14 @@ datetime_to_char(DateTime *dt, text *fmt)
        tm->tm_mday     =1;     tm->tm_isdst    =0;
        tm->tm_mon      =1;
 
-       if (DATETIME_IS_EPOCH(*dt))
+       if (TIMESTAMP_IS_EPOCH(*dt))
        {
-               datetime2tm(SetDateTime(*dt), NULL, tm, &fsec, NULL);
-       } else if (DATETIME_IS_CURRENT(*dt)) {
-               datetime2tm(SetDateTime(*dt), &tz, tm, &fsec, &tzn);
+               timestamp2tm(SetTimestamp(*dt), NULL, tm, &fsec, NULL);
+       } else if (TIMESTAMP_IS_CURRENT(*dt)) {
+               timestamp2tm(SetTimestamp(*dt), &tz, tm, &fsec, &tzn);
        } else {
-               if (datetime2tm(*dt, &tz, tm, &fsec, &tzn) != 0)
-                       elog(ERROR, "to_char(): Unable to convert datetime to tm");
+               if (timestamp2tm(*dt, &tz, tm, &fsec, &tzn) != 0)
+                       elog(ERROR, "to_char(): Unable to convert timestamp to tm");
        }
 
        tm->tm_wday = (date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) + 1) % 7; 
@@ -1902,32 +1902,22 @@ datetime_to_char(DateTime *dt, text *fmt)
 }
 
 
-/* -------------------
- * TIMESTAMP to_char()
- * -------------------
- */
-text *
-timestamp_to_char(time_t dt, text *fmt)
-{
-       return datetime_to_char( timestamp_datetime(dt), fmt);
-}
-
 /* ---------------------
- * TO_DATETIME()
+ * TO_TIMESTAMP()
  *
- * Make DateTime from date_str which is formated at argument 'fmt'      
- * ( to_datetime is reverse to_char() )
+ * Make Timestamp from date_str which is formated at argument 'fmt'     
+ * ( to_timestamp is reverse to_char() )
  * ---------------------
  */
-DateTime *
-to_datetime(text *date_str, text *fmt)
+Timestamp *
+to_timestamp(text *date_str, text *fmt)
 {
        static FormatNode       CacheFormat[ DCH_CACHE_SIZE +1];
        static char             CacheStr[ DCH_CACHE_SIZE +1];
 
        FormatNode              *format;
        int                     flag=0;
-       DateTime                *result;
+       Timestamp               *result;
        char                    *str;
        int                     len=0,
                                fsec=0,
@@ -1942,7 +1932,7 @@ to_datetime(text *date_str, text *fmt)
        tm->tm_mday     =1;     tm->tm_isdst    =0;
        tm->tm_mon      =1;
        
-       result = palloc(sizeof(DateTime));
+       result = palloc(sizeof(Timestamp));
        
        len     = VARSIZE(fmt) - VARHDRSZ; 
        
@@ -2060,8 +2050,8 @@ to_datetime(text *date_str, text *fmt)
 #ifdef DEBUG_TO_FROM_CHAR
        NOTICE_TM; 
 #endif
-       if (tm2datetime(tm, fsec, &tz, result) != 0)
-               elog(ERROR, "to_datatime()/to_timestamp(): can't convert 'tm' to datetime.");
+       if (tm2timestamp(tm, fsec, &tz, result) != 0)
+               elog(ERROR, "to_datatime(): can't convert 'tm' to timestamp.");
        
        return result;
 }
@@ -2074,18 +2064,7 @@ to_datetime(text *date_str, text *fmt)
 DateADT  
 to_date(text *date_str, text *fmt)
 {
-       return datetime_date( to_datetime(date_str, fmt) );
-}
-
-/* ----------
- * TO_TIMESTAMP 
- *     Make timestamp from date_str which is formated at argument 'fmt'         
- * ----------
- */
-time_t  
-to_timestamp(text *date_str, text *fmt)
-{
-       return datetime_timestamp( to_datetime(date_str, fmt) );
+       return timestamp_date( to_timestamp(date_str, fmt) );
 }
 
 /**********************************************************************
index 71a636feeb3583f6b25105ea25ea094806c463ec..28a94f5e168f272cb7ddc01ca7a62b8a6fe4f19a 100644 (file)
@@ -1,23 +1,41 @@
 /*
  * nabstime.c
- *       parse almost any absolute date getdate(3) can (& some it can't)
+ *       Utilities for the built-in type "AbsoluteTime".
+ *       Functions for the built-in type "RelativeTime".
+ *       Functions for the built-in type "TimeInterval".
  *
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- *       $Id: nabstime.c,v 1.65 2000/01/26 05:57:14 momjian Exp $
  *
+ * IDENTIFICATION
+ *       $Header: /cvsroot/pgsql/src/backend/utils/adt/nabstime.c,v 1.66 2000/02/16 17:24:48 thomas Exp $
+ *
+ * NOTES
+ *
+ *-------------------------------------------------------------------------
  */
 #include <ctype.h>
+#include <time.h>
+#include <sys/time.h>
 #include <sys/types.h>
 
 #include "postgres.h"
 #ifdef HAVE_FLOAT_H
 #include <float.h>
 #endif
+
 #ifdef HAVE_LIMITS_H
 #include <limits.h>
+#ifndef MAXINT
+#define MAXINT INT_MAX
+#endif
+#else
+#ifdef HAVE_VALUES_H
+#include <values.h>
+#endif
 #endif
+
 #ifndef USE_POSIX_TIME
 #include <sys/timeb.h>
 #endif
 #include "miscadmin.h"
 #include "utils/builtins.h"
 
+
+#if 0
 static AbsoluteTime tm2abstime(struct tm * tm, int tz);
+#endif
+
 
 #define MIN_DAYNUM -24856              /* December 13, 1901 */
 #define MAX_DAYNUM 24854               /* January 18, 2038 */
 
+#define INVALID_RELTIME_STR            "Undefined RelTime"
+#define INVALID_RELTIME_STR_LEN (sizeof(INVALID_RELTIME_STR)-1)
+#define RELTIME_LABEL                  '@'
+#define RELTIME_PAST                   "ago"
+#define DIRMAXLEN                              (sizeof(RELTIME_PAST)-1)
+
+/*
+ * Unix epoch is Jan  1 00:00:00 1970.
+ * Postgres knows about times sixty-eight years on either side of that
+ * for these 4-byte types.
+ *
+ * "tinterval" is two 4-byte fields.
+ * Definitions for parsing tinterval.
+ */
+
+#define IsSpace(C)                             ((C) == ' ')
+
+#define T_INTERVAL_INVAL   0   /* data represents no valid interval */
+#define T_INTERVAL_VALID   1   /* data represents a valid interval */
+/*
+ * ['Mon May 10 23:59:12 1943 PST' 'Sun Jan 14 03:14:21 1973 PST']
+ * 0           1                 2                     3                 4                     5                 6
+ * 1234567890123456789012345678901234567890123456789012345678901234
+ *
+ * we allocate some extra -- timezones are usually 3 characters but
+ * this is not in the POSIX standard...
+ */
+#define T_INTERVAL_LEN                                 80
+#define INVALID_INTERVAL_STR                   "Undefined Range"
+#define INVALID_INTERVAL_STR_LEN               (sizeof(INVALID_INTERVAL_STR)-1)
+
+#define ABSTIMEMIN(t1, t2) abstimele((t1),(t2)) ? (t1) : (t2)
+#define ABSTIMEMAX(t1, t2) abstimelt((t1),(t2)) ? (t2) : (t1)
+
+#ifdef NOT_USED
+static char *unit_tab[] = {
+       "second", "seconds", "minute", "minutes",
+       "hour", "hours", "day", "days", "week", "weeks",
+"month", "months", "year", "years"};
+
+#define UNITMAXLEN 7                   /* max length of a unit name */
+#define NUNITS 14                              /* number of different units */
+
+/* table of seconds per unit (month = 30 days, year = 365 days)  */
+static int     sec_tab[] = {
+       1, 1, 60, 60,
+       3600, 3600, 86400, 86400, 604800, 604800,
+2592000, 2592000, 31536000, 31536000};
+#endif
+
+/*
+ * Function prototypes -- internal to this file only
+ */
+
+static void reltime2tm(RelativeTime time, struct tm * tm);
+
+#ifdef NOT_USED
+static int     correct_unit(char *unit, int *unptr);
+static int     correct_dir(char *direction, int *signptr);
+
+#endif
+
+static int istinterval(char *i_string,
+                       AbsoluteTime *i_start,
+                       AbsoluteTime *i_end);
 
 /* GetCurrentAbsoluteTime()
  * Get the current system time. Set timezone parameters if not specified elsewhere.
@@ -491,10 +578,10 @@ abstimege(AbsoluteTime t1, AbsoluteTime t2)
 
 
 /* datetime_abstime()
- * Convert datetime to abstime.
+ * Convert timestamp to abstime.
  */
 AbsoluteTime
-datetime_abstime(DateTime *datetime)
+timestamp_abstime(Timestamp *timestamp)
 {
        AbsoluteTime result;
 
@@ -502,35 +589,35 @@ datetime_abstime(DateTime *datetime)
        struct tm       tt,
                           *tm = &tt;
 
-       if (!PointerIsValid(datetime))
+       if (!PointerIsValid(timestamp))
        {
                result = INVALID_ABSTIME;
 
        }
-       else if (DATETIME_IS_INVALID(*datetime))
+       else if (TIMESTAMP_IS_INVALID(*timestamp))
        {
                result = INVALID_ABSTIME;
 
        }
-       else if (DATETIME_IS_NOBEGIN(*datetime))
+       else if (TIMESTAMP_IS_NOBEGIN(*timestamp))
        {
                result = NOSTART_ABSTIME;
 
        }
-       else if (DATETIME_IS_NOEND(*datetime))
+       else if (TIMESTAMP_IS_NOEND(*timestamp))
        {
                result = NOEND_ABSTIME;
 
        }
        else
        {
-               if (DATETIME_IS_RELATIVE(*datetime))
+               if (TIMESTAMP_IS_RELATIVE(*timestamp))
                {
-                       datetime2tm(SetDateTime(*datetime), NULL, tm, &fsec, NULL);
+                       timestamp2tm(SetTimestamp(*timestamp), NULL, tm, &fsec, NULL);
                        result = tm2abstime(tm, 0);
 
                }
-               else if (datetime2tm(*datetime, NULL, tm, &fsec, NULL) == 0)
+               else if (timestamp2tm(*timestamp, NULL, tm, &fsec, NULL) == 0)
                {
                        result = tm2abstime(tm, 0);
 
@@ -542,39 +629,39 @@ datetime_abstime(DateTime *datetime)
        };
 
        return result;
-}      /* datetime_abstime() */
+}      /* timestamp_abstime() */
 
-/* abstime_datetime()
- * Convert abstime to datetime.
+/* abstime_timestamp()
+ * Convert abstime to timestamp.
  */
-DateTime   *
-abstime_datetime(AbsoluteTime abstime)
+Timestamp   *
+abstime_timestamp(AbsoluteTime abstime)
 {
-       DateTime   *result;
+       Timestamp   *result;
 
-       if (!PointerIsValid(result = palloc(sizeof(DateTime))))
-               elog(ERROR, "Unable to allocate space to convert abstime to datetime");
+       if (!PointerIsValid(result = palloc(sizeof(Timestamp))))
+               elog(ERROR, "Unable to allocate space to convert abstime to timestamp");
 
        switch (abstime)
        {
                case INVALID_ABSTIME:
-                       DATETIME_INVALID(*result);
+                       TIMESTAMP_INVALID(*result);
                        break;
 
                case NOSTART_ABSTIME:
-                       DATETIME_NOBEGIN(*result);
+                       TIMESTAMP_NOBEGIN(*result);
                        break;
 
                case NOEND_ABSTIME:
-                       DATETIME_NOEND(*result);
+                       TIMESTAMP_NOEND(*result);
                        break;
 
                case EPOCH_ABSTIME:
-                       DATETIME_EPOCH(*result);
+                       TIMESTAMP_EPOCH(*result);
                        break;
 
                case CURRENT_ABSTIME:
-                       DATETIME_CURRENT(*result);
+                       TIMESTAMP_CURRENT(*result);
                        break;
 
                default:
@@ -583,4 +670,1195 @@ abstime_datetime(AbsoluteTime abstime)
        };
 
        return result;
-}      /* abstime_datetime() */
+}      /* abstime_timestamp() */
+
+
+/*****************************************************************************
+ *      USER I/O ROUTINES                                                                                                               *
+ *****************************************************************************/
+
+/*
+ *             reltimein               - converts a reltime string in an internal format
+ */
+RelativeTime
+reltimein(char *str)
+{
+       RelativeTime result;
+
+       struct tm       tt,
+                          *tm = &tt;
+       double          fsec;
+       int                     dtype;
+       char       *field[MAXDATEFIELDS];
+       int                     nf,
+                               ftype[MAXDATEFIELDS];
+       char            lowstr[MAXDATELEN + 1];
+
+       if (!PointerIsValid(str))
+               elog(ERROR, "Bad (null) date external representation");
+
+       if (strlen(str) > MAXDATELEN)
+               elog(ERROR, "Bad (length) reltime external representation '%s'", str);
+
+       if ((ParseDateTime(str, lowstr, field, ftype, MAXDATEFIELDS, &nf) != 0)
+               || (DecodeDateDelta(field, ftype, nf, &dtype, tm, &fsec) != 0))
+               elog(ERROR, "Bad reltime external representation '%s'", str);
+
+       switch (dtype)
+       {
+               case DTK_DELTA:
+                       result = ((((tm->tm_hour * 60) + tm->tm_min) * 60) + tm->tm_sec);
+                       result += (((tm->tm_year * 365) + (tm->tm_mon * 30) + tm->tm_mday) * (24 * 60 * 60));
+                       return result;
+
+               default:
+                       return INVALID_RELTIME;
+       }
+
+       elog(ERROR, "Bad reltime (internal coding error) '%s'", str);
+       return INVALID_RELTIME;
+}      /* reltimein() */
+
+
+/*
+ *             reltimeout              - converts the internal format to a reltime string
+ */
+char *
+reltimeout(RelativeTime time)
+{
+       char       *result;
+       struct tm       tt,
+                          *tm = &tt;
+       char            buf[MAXDATELEN + 1];
+
+       if (time == INVALID_RELTIME)
+       {
+               strcpy(buf, INVALID_RELTIME_STR);
+
+       }
+       else
+       {
+               reltime2tm(time, tm);
+               EncodeTimeSpan(tm, 0, DateStyle, buf);
+       }
+
+       result = palloc(strlen(buf) + 1);
+       strcpy(result, buf);
+
+       return result;
+}      /* reltimeout() */
+
+
+static void
+reltime2tm(RelativeTime time, struct tm * tm)
+{
+       TMODULO(time, tm->tm_year, 31536000);
+       TMODULO(time, tm->tm_mon, 2592000);
+       TMODULO(time, tm->tm_mday, 86400);
+       TMODULO(time, tm->tm_hour, 3600);
+       TMODULO(time, tm->tm_min, 60);
+       TMODULO(time, tm->tm_sec, 1);
+
+       return;
+}      /* reltime2tm() */
+
+#ifdef NOT_USED
+int
+dummyfunc()
+{
+       char       *timestring;
+       long            quantity;
+       int                     i;
+       int                     unitnr;
+
+       timestring = (char *) palloc(Max(strlen(INVALID_RELTIME_STR),
+                                                                        UNITMAXLEN) + 1);
+       if (timevalue == INVALID_RELTIME)
+       {
+               strcpy(timestring, INVALID_RELTIME_STR);
+               return timestring;
+       }
+
+       if (timevalue == 0)
+               i = 1;                                  /* unit = 'seconds' */
+       else
+               for (i = 12; i >= 0; i = i - 2)
+                       if ((timevalue % sec_tab[i]) == 0)
+                               break;                  /* appropriate unit found */
+       unitnr = i;
+       quantity = (timevalue / sec_tab[unitnr]);
+       if (quantity > 1 || quantity < -1)
+               unitnr++;                               /* adjust index for PLURAL of unit */
+       if (quantity >= 0)
+               sprintf(timestring, "%c %lu %s", RELTIME_LABEL,
+                               quantity, unit_tab[unitnr]);
+       else
+               sprintf(timestring, "%c %lu %s %s", RELTIME_LABEL,
+                               (quantity * -1), unit_tab[unitnr], RELTIME_PAST);
+       return timestring;
+}
+
+#endif
+
+
+/*
+ *             tintervalin             - converts an interval string to an internal format
+ */
+TimeInterval
+tintervalin(char *intervalstr)
+{
+       int                     error;
+       AbsoluteTime i_start,
+                               i_end,
+                               t1,
+                               t2;
+       TimeInterval interval;
+
+       interval = (TimeInterval) palloc(sizeof(TimeIntervalData));
+       error = istinterval(intervalstr, &t1, &t2);
+       if (error == 0)
+               interval->status = T_INTERVAL_INVAL;
+       if (t1 == INVALID_ABSTIME || t2 == INVALID_ABSTIME)
+               interval->status = T_INTERVAL_INVAL;    /* undefined  */
+       else
+       {
+               i_start = ABSTIMEMIN(t1, t2);
+               i_end = ABSTIMEMAX(t1, t2);
+               interval->data[0] = i_start;
+               interval->data[1] = i_end;
+               interval->status = T_INTERVAL_VALID;
+       }
+       return interval;
+}
+
+
+/*
+ *             tintervalout    - converts an internal interval format to a string
+ *
+ */
+char *
+tintervalout(TimeInterval interval)
+{
+       char       *i_str,
+                          *p;
+
+       i_str = (char *) palloc(T_INTERVAL_LEN);        /* ['...' '...'] */
+       strcpy(i_str, "[\"");
+       if (interval->status == T_INTERVAL_INVAL)
+               strcat(i_str, INVALID_INTERVAL_STR);
+       else
+       {
+               p = nabstimeout(interval->data[0]);
+               strcat(i_str, p);
+               pfree(p);
+               strcat(i_str, "\" \"");
+               p = nabstimeout(interval->data[1]);
+               strcat(i_str, p);
+               pfree(p);
+       }
+       strcat(i_str, "\"]\0");
+       return i_str;
+}
+
+
+/*****************************************************************************
+ *      PUBLIC ROUTINES                                                                                                                 *
+ *****************************************************************************/
+
+RelativeTime
+interval_reltime(Interval *interval)
+{
+       RelativeTime time;
+       int                     year,
+                               month;
+       double          span;
+
+       if (!PointerIsValid(interval))
+               time = INVALID_RELTIME;
+
+       if (INTERVAL_IS_INVALID(*interval))
+       {
+               time = INVALID_RELTIME;
+
+       }
+       else
+       {
+               if (interval->month == 0)
+               {
+                       year = 0;
+                       month = 0;
+
+               }
+               else if (abs(interval->month) >= 12)
+               {
+                       year = (interval->month / 12);
+                       month = (interval->month % 12);
+
+               }
+               else
+               {
+                       year = 0;
+                       month = interval->month;
+               }
+
+               span = (((((double) 365 * year) + ((double) 30 * month)) * 86400) + interval->time);
+
+               time = (((span > INT_MIN) && (span < INT_MAX)) ? span : INVALID_RELTIME);
+       }
+
+       return time;
+}      /* interval_reltime() */
+
+
+Interval   *
+reltime_interval(RelativeTime reltime)
+{
+       Interval   *result;
+       int                     year,
+                               month;
+
+       if (!PointerIsValid(result = palloc(sizeof(Interval))))
+               elog(ERROR, "Memory allocation failed, can't convert reltime to interval");
+
+       switch (reltime)
+       {
+               case INVALID_RELTIME:
+                       INTERVAL_INVALID(*result);
+                       break;
+
+               default:
+                       TMODULO(reltime, year, 31536000);
+                       TMODULO(reltime, month, 2592000);
+
+                       result->time = reltime;
+                       result->month = ((12 * year) + month);
+       }
+
+       return result;
+}      /* reltime_interval() */
+
+
+/*
+ *             mktinterval             - creates a time interval with endpoints t1 and t2
+ */
+TimeInterval
+mktinterval(AbsoluteTime t1, AbsoluteTime t2)
+{
+       AbsoluteTime tstart = ABSTIMEMIN(t1, t2),
+                               tend = ABSTIMEMAX(t1, t2);
+       TimeInterval interval;
+
+       interval = (TimeInterval) palloc(sizeof(TimeIntervalData));
+       if (t1 == INVALID_ABSTIME || t2 == INVALID_ABSTIME)
+               interval->status = T_INTERVAL_INVAL;
+       else
+       {
+               interval->status = T_INTERVAL_VALID;
+               interval->data[0] = tstart;
+               interval->data[1] = tend;
+       }
+
+       return interval;
+}
+
+/*
+ *             timepl, timemi and abstimemi use the formula
+ *                             abstime + reltime = abstime
+ *             so              abstime - reltime = abstime
+ *             and             abstime - abstime = reltime
+ */
+
+/*
+ *             timepl                  - returns the value of (abstime t1 + relime t2)
+ */
+AbsoluteTime
+timepl(AbsoluteTime t1, RelativeTime t2)
+{
+       if (t1 == CURRENT_ABSTIME)
+               t1 = GetCurrentTransactionStartTime();
+
+       if (AbsoluteTimeIsReal(t1) &&
+               RelativeTimeIsValid(t2) &&
+               ((t2 > 0) ? (t1 < NOEND_ABSTIME - t2)
+                : (t1 > NOSTART_ABSTIME - t2)))                /* prevent overflow */
+               return t1 + t2;
+
+       return INVALID_ABSTIME;
+}
+
+
+/*
+ *             timemi                  - returns the value of (abstime t1 - reltime t2)
+ */
+AbsoluteTime
+timemi(AbsoluteTime t1, RelativeTime t2)
+{
+       if (t1 == CURRENT_ABSTIME)
+               t1 = GetCurrentTransactionStartTime();
+
+       if (AbsoluteTimeIsReal(t1) &&
+               RelativeTimeIsValid(t2) &&
+               ((t2 > 0) ? (t1 > NOSTART_ABSTIME + t2)
+                : (t1 < NOEND_ABSTIME + t2)))  /* prevent overflow */
+               return t1 - t2;
+
+       return INVALID_ABSTIME;
+}
+
+
+/*
+ *             abstimemi               - returns the value of (abstime t1 - abstime t2)
+ */
+static RelativeTime
+abstimemi(AbsoluteTime t1, AbsoluteTime t2)
+{
+       if (t1 == CURRENT_ABSTIME)
+               t1 = GetCurrentTransactionStartTime();
+       if (t2 == CURRENT_ABSTIME)
+               t2 = GetCurrentTransactionStartTime();
+
+       if (AbsoluteTimeIsReal(t1) &&
+               AbsoluteTimeIsReal(t2))
+               return t1 - t2;
+
+       return INVALID_RELTIME;
+}
+
+
+/*
+ *             intinterval             - returns 1, iff absolute date is in the interval
+ */
+int
+intinterval(AbsoluteTime t, TimeInterval interval)
+{
+       if (interval->status == T_INTERVAL_VALID && t != INVALID_ABSTIME)
+               return (abstimege(t, interval->data[0]) &&
+                               abstimele(t, interval->data[1]));
+       return 0;
+}
+
+/*
+ *             tintervalrel            - returns  relative time corresponding to interval
+ */
+RelativeTime
+tintervalrel(TimeInterval interval)
+{
+       if (interval->status == T_INTERVAL_VALID)
+               return abstimemi(interval->data[1], interval->data[0]);
+       else
+               return INVALID_RELTIME;
+}
+
+/*
+ *             timenow                 - returns  time "now", internal format
+ *
+ *             Now AbsoluteTime is time since Jan 1 1970 -mer 7 Feb 1992
+ */
+AbsoluteTime
+timenow()
+{
+       time_t          sec;
+
+       if (time(&sec) < 0)
+               return INVALID_ABSTIME;
+       return (AbsoluteTime) sec;
+}
+
+/*
+ *             reltimeeq               - returns 1, iff arguments are equal
+ *             reltimene               - returns 1, iff arguments are not equal
+ *             reltimelt               - returns 1, iff t1 less than t2
+ *             reltimegt               - returns 1, iff t1 greater than t2
+ *             reltimele               - returns 1, iff t1 less than or equal to t2
+ *             reltimege               - returns 1, iff t1 greater than or equal to t2
+ */
+bool
+reltimeeq(RelativeTime t1, RelativeTime t2)
+{
+       if (t1 == INVALID_RELTIME || t2 == INVALID_RELTIME)
+               return 0;
+       return t1 == t2;
+}
+
+bool
+reltimene(RelativeTime t1, RelativeTime t2)
+{
+       if (t1 == INVALID_RELTIME || t2 == INVALID_RELTIME)
+               return 0;
+       return t1 != t2;
+}
+
+bool
+reltimelt(RelativeTime t1, RelativeTime t2)
+{
+       if (t1 == INVALID_RELTIME || t2 == INVALID_RELTIME)
+               return 0;
+       return t1 < t2;
+}
+
+bool
+reltimegt(RelativeTime t1, RelativeTime t2)
+{
+       if (t1 == INVALID_RELTIME || t2 == INVALID_RELTIME)
+               return 0;
+       return t1 > t2;
+}
+
+bool
+reltimele(RelativeTime t1, RelativeTime t2)
+{
+       if (t1 == INVALID_RELTIME || t2 == INVALID_RELTIME)
+               return 0;
+       return t1 <= t2;
+}
+
+bool
+reltimege(RelativeTime t1, RelativeTime t2)
+{
+       if (t1 == INVALID_RELTIME || t2 == INVALID_RELTIME)
+               return 0;
+       return t1 >= t2;
+}
+
+
+/*
+ *             tintervalsame   - returns 1, iff interval i1 is same as interval i2
+ *             Check begin and end time.
+ */
+bool
+tintervalsame(TimeInterval i1, TimeInterval i2)
+{
+       if (i1->status == T_INTERVAL_INVAL || i2->status == T_INTERVAL_INVAL)
+               return FALSE;                   /* invalid interval */
+       return (abstimeeq(i1->data[0], i2->data[0]) &&
+                       abstimeeq(i1->data[1], i2->data[1]));
+}      /* tintervalsame() */
+
+
+/*
+ *             tintervaleq             - returns 1, iff interval i1 is equal to interval i2
+ *             Check length of intervals.
+ */
+bool
+tintervaleq(TimeInterval i1, TimeInterval i2)
+{
+       AbsoluteTime t10,
+                               t11,
+                               t20,
+                               t21;
+
+       if (i1->status == T_INTERVAL_INVAL || i2->status == T_INTERVAL_INVAL)
+               return FALSE;                   /* invalid interval */
+
+       t10 = i1->data[0];
+       t11 = i1->data[1];
+       t20 = i2->data[0];
+       t21 = i2->data[1];
+
+       if ((t10 == INVALID_ABSTIME) || (t20 == INVALID_ABSTIME)
+               || (t20 == INVALID_ABSTIME) || (t21 == INVALID_ABSTIME))
+               return FALSE;
+
+       if (t10 == CURRENT_ABSTIME)
+               t10 = GetCurrentTransactionStartTime();
+       if (t11 == CURRENT_ABSTIME)
+               t11 = GetCurrentTransactionStartTime();
+       if (t20 == CURRENT_ABSTIME)
+               t20 = GetCurrentTransactionStartTime();
+       if (t21 == CURRENT_ABSTIME)
+               t21 = GetCurrentTransactionStartTime();
+
+       return (t11 - t10) == (t21 - t20);
+}      /* tintervaleq() */
+
+/*
+ *             tintervalne             - returns 1, iff interval i1 is not equal to interval i2
+ *             Check length of intervals.
+ */
+bool
+tintervalne(TimeInterval i1, TimeInterval i2)
+{
+       AbsoluteTime t10,
+                               t11,
+                               t20,
+                               t21;
+
+       if (i1->status == T_INTERVAL_INVAL || i2->status == T_INTERVAL_INVAL)
+               return FALSE;                   /* invalid interval */
+
+       t10 = i1->data[0];
+       t11 = i1->data[1];
+       t20 = i2->data[0];
+       t21 = i2->data[1];
+
+       if ((t10 == INVALID_ABSTIME) || (t20 == INVALID_ABSTIME)
+               || (t20 == INVALID_ABSTIME) || (t21 == INVALID_ABSTIME))
+               return FALSE;
+
+       if (t10 == CURRENT_ABSTIME)
+               t10 = GetCurrentTransactionStartTime();
+       if (t11 == CURRENT_ABSTIME)
+               t11 = GetCurrentTransactionStartTime();
+       if (t20 == CURRENT_ABSTIME)
+               t20 = GetCurrentTransactionStartTime();
+       if (t21 == CURRENT_ABSTIME)
+               t21 = GetCurrentTransactionStartTime();
+
+       return (t11 - t10) != (t21 - t20);
+}      /* tintervalne() */
+
+/*
+ *             tintervallt             - returns TRUE, iff interval i1 is less than interval i2
+ *             Check length of intervals.
+ */
+bool
+tintervallt(TimeInterval i1, TimeInterval i2)
+{
+       AbsoluteTime t10,
+                               t11,
+                               t20,
+                               t21;
+
+       if (i1->status == T_INTERVAL_INVAL || i2->status == T_INTERVAL_INVAL)
+               return FALSE;                   /* invalid interval */
+
+       t10 = i1->data[0];
+       t11 = i1->data[1];
+       t20 = i2->data[0];
+       t21 = i2->data[1];
+
+       if ((t10 == INVALID_ABSTIME) || (t20 == INVALID_ABSTIME)
+               || (t20 == INVALID_ABSTIME) || (t21 == INVALID_ABSTIME))
+               return FALSE;
+
+       if (t10 == CURRENT_ABSTIME)
+               t10 = GetCurrentTransactionStartTime();
+       if (t11 == CURRENT_ABSTIME)
+               t11 = GetCurrentTransactionStartTime();
+       if (t20 == CURRENT_ABSTIME)
+               t20 = GetCurrentTransactionStartTime();
+       if (t21 == CURRENT_ABSTIME)
+               t21 = GetCurrentTransactionStartTime();
+
+       return (t11 - t10) < (t21 - t20);
+}      /* tintervallt() */
+
+/*
+ *             tintervalle             - returns TRUE, iff interval i1 is less than or equal to interval i2
+ *             Check length of intervals.
+ */
+bool
+tintervalle(TimeInterval i1, TimeInterval i2)
+{
+       AbsoluteTime t10,
+                               t11,
+                               t20,
+                               t21;
+
+       if (i1->status == T_INTERVAL_INVAL || i2->status == T_INTERVAL_INVAL)
+               return FALSE;                   /* invalid interval */
+
+       t10 = i1->data[0];
+       t11 = i1->data[1];
+       t20 = i2->data[0];
+       t21 = i2->data[1];
+
+       if ((t10 == INVALID_ABSTIME) || (t20 == INVALID_ABSTIME)
+               || (t20 == INVALID_ABSTIME) || (t21 == INVALID_ABSTIME))
+               return FALSE;
+
+       if (t10 == CURRENT_ABSTIME)
+               t10 = GetCurrentTransactionStartTime();
+       if (t11 == CURRENT_ABSTIME)
+               t11 = GetCurrentTransactionStartTime();
+       if (t20 == CURRENT_ABSTIME)
+               t20 = GetCurrentTransactionStartTime();
+       if (t21 == CURRENT_ABSTIME)
+               t21 = GetCurrentTransactionStartTime();
+
+       return (t11 - t10) <= (t21 - t20);
+}      /* tintervalle() */
+
+/*
+ *             tintervalgt             - returns TRUE, iff interval i1 is less than interval i2
+ *             Check length of intervals.
+ */
+bool
+tintervalgt(TimeInterval i1, TimeInterval i2)
+{
+       AbsoluteTime t10,
+                               t11,
+                               t20,
+                               t21;
+
+       if (i1->status == T_INTERVAL_INVAL || i2->status == T_INTERVAL_INVAL)
+               return FALSE;                   /* invalid interval */
+
+       t10 = i1->data[0];
+       t11 = i1->data[1];
+       t20 = i2->data[0];
+       t21 = i2->data[1];
+
+       if ((t10 == INVALID_ABSTIME) || (t20 == INVALID_ABSTIME)
+               || (t20 == INVALID_ABSTIME) || (t21 == INVALID_ABSTIME))
+               return FALSE;
+
+       if (t10 == CURRENT_ABSTIME)
+               t10 = GetCurrentTransactionStartTime();
+       if (t11 == CURRENT_ABSTIME)
+               t11 = GetCurrentTransactionStartTime();
+       if (t20 == CURRENT_ABSTIME)
+               t20 = GetCurrentTransactionStartTime();
+       if (t21 == CURRENT_ABSTIME)
+               t21 = GetCurrentTransactionStartTime();
+
+       return (t11 - t10) > (t21 - t20);
+}      /* tintervalgt() */
+
+/*
+ *             tintervalge             - returns TRUE, iff interval i1 is less than or equal to interval i2
+ *             Check length of intervals.
+ */
+bool
+tintervalge(TimeInterval i1, TimeInterval i2)
+{
+       AbsoluteTime t10,
+                               t11,
+                               t20,
+                               t21;
+
+       if (i1->status == T_INTERVAL_INVAL || i2->status == T_INTERVAL_INVAL)
+               return FALSE;                   /* invalid interval */
+
+       t10 = i1->data[0];
+       t11 = i1->data[1];
+       t20 = i2->data[0];
+       t21 = i2->data[1];
+
+       if ((t10 == INVALID_ABSTIME) || (t20 == INVALID_ABSTIME)
+               || (t20 == INVALID_ABSTIME) || (t21 == INVALID_ABSTIME))
+               return FALSE;
+
+       if (t10 == CURRENT_ABSTIME)
+               t10 = GetCurrentTransactionStartTime();
+       if (t11 == CURRENT_ABSTIME)
+               t11 = GetCurrentTransactionStartTime();
+       if (t20 == CURRENT_ABSTIME)
+               t20 = GetCurrentTransactionStartTime();
+       if (t21 == CURRENT_ABSTIME)
+               t21 = GetCurrentTransactionStartTime();
+
+       return (t11 - t10) >= (t21 - t20);
+}      /* tintervalge() */
+
+
+/*
+ *             tintervalleneq  - returns 1, iff length of interval i is equal to
+ *                                                             reltime t
+ */
+bool
+tintervalleneq(TimeInterval i, RelativeTime t)
+{
+       RelativeTime rt;
+
+       if ((i->status == T_INTERVAL_INVAL) || (t == INVALID_RELTIME))
+               return 0;
+       rt = tintervalrel(i);
+       return rt != INVALID_RELTIME && rt == t;
+}
+
+/*
+ *             tintervallenne  - returns 1, iff length of interval i is not equal
+ *                                                             to reltime t
+ */
+bool
+tintervallenne(TimeInterval i, RelativeTime t)
+{
+       RelativeTime rt;
+
+       if ((i->status == T_INTERVAL_INVAL) || (t == INVALID_RELTIME))
+               return 0;
+       rt = tintervalrel(i);
+       return rt != INVALID_RELTIME && rt != t;
+}
+
+/*
+ *             tintervallenlt  - returns 1, iff length of interval i is less than
+ *                                                             reltime t
+ */
+bool
+tintervallenlt(TimeInterval i, RelativeTime t)
+{
+       RelativeTime rt;
+
+       if ((i->status == T_INTERVAL_INVAL) || (t == INVALID_RELTIME))
+               return 0;
+       rt = tintervalrel(i);
+       return rt != INVALID_RELTIME && rt < t;
+}
+
+/*
+ *             tintervallengt  - returns 1, iff length of interval i is greater than
+ *                                                             reltime t
+ */
+bool
+tintervallengt(TimeInterval i, RelativeTime t)
+{
+       RelativeTime rt;
+
+       if ((i->status == T_INTERVAL_INVAL) || (t == INVALID_RELTIME))
+               return 0;
+       rt = tintervalrel(i);
+       return rt != INVALID_RELTIME && rt > t;
+}
+
+/*
+ *             tintervallenle  - returns 1, iff length of interval i is less or equal
+ *                                                                     than reltime t
+ */
+bool
+tintervallenle(TimeInterval i, RelativeTime t)
+{
+       RelativeTime rt;
+
+       if ((i->status == T_INTERVAL_INVAL) || (t == INVALID_RELTIME))
+               return 0;
+       rt = tintervalrel(i);
+       return rt != INVALID_RELTIME && rt <= t;
+}
+
+/*
+ *             tintervallenge  - returns 1, iff length of interval i is greater or
+ *                                                             equal than reltime t
+ */
+bool
+tintervallenge(TimeInterval i, RelativeTime t)
+{
+       RelativeTime rt;
+
+       if ((i->status == T_INTERVAL_INVAL) || (t == INVALID_RELTIME))
+               return 0;
+       rt = tintervalrel(i);
+       return rt != INVALID_RELTIME && rt >= t;
+}
+
+/*
+ *             tintervalct             - returns 1, iff interval i1 contains interval i2
+ */
+bool
+tintervalct(TimeInterval i1, TimeInterval i2)
+{
+       if (i1->status == T_INTERVAL_INVAL || i2->status == T_INTERVAL_INVAL)
+               return 0;
+       return (abstimele(i1->data[0], i2->data[0]) &&
+                       abstimege(i1->data[1], i2->data[1]));
+}
+
+/*
+ *             tintervalov             - returns 1, iff interval i1 (partially) overlaps i2
+ */
+bool
+tintervalov(TimeInterval i1, TimeInterval i2)
+{
+       if (i1->status == T_INTERVAL_INVAL || i2->status == T_INTERVAL_INVAL)
+               return 0;
+       return (!(abstimelt(i1->data[1], i2->data[0]) ||
+                         abstimegt(i1->data[0], i2->data[1])));
+}
+
+/*
+ *             tintervalstart  - returns  the start of interval i
+ */
+AbsoluteTime
+tintervalstart(TimeInterval i)
+{
+       if (i->status == T_INTERVAL_INVAL)
+               return INVALID_ABSTIME;
+       return i->data[0];
+}
+
+/*
+ *             tintervalend            - returns  the end of interval i
+ */
+AbsoluteTime
+tintervalend(TimeInterval i)
+{
+       if (i->status == T_INTERVAL_INVAL)
+               return INVALID_ABSTIME;
+       return i->data[1];
+}
+
+
+/*****************************************************************************
+ *      PRIVATE ROUTINES                                                                                                                *
+ *****************************************************************************/
+
+#ifdef NOT_USED
+/*
+ *             isreltime               - returns 1, iff datestring is of type reltime
+ *                                                               2, iff datestring is 'invalid time' identifier
+ *                                                               0, iff datestring contains a syntax error
+ *             VALID time      less or equal +/-  `@ 68 years'
+ *
+ */
+int
+isreltime(char *str)
+{
+       struct tm       tt,
+                          *tm = &tt;
+       double          fsec;
+       int                     dtype;
+       char       *field[MAXDATEFIELDS];
+       int                     nf,
+                               ftype[MAXDATEFIELDS];
+       char            lowstr[MAXDATELEN + 1];
+
+       if (!PointerIsValid(str))
+               return 0;
+
+       if (strlen(str) > MAXDATELEN)
+               return 0;
+
+       if ((ParseDateTime(str, lowstr, field, ftype, MAXDATEFIELDS, &nf) != 0)
+               || (DecodeDateDelta(field, ftype, nf, &dtype, tm, &fsec) != 0))
+               return 0;
+
+       switch (dtype)
+       {
+               case (DTK_DELTA):
+                       return (abs(tm->tm_year) <= 68) ? 1 : 0;
+                       break;
+
+               case (DTK_INVALID):
+                       return 2;
+                       break;
+
+               default:
+                       return 0;
+                       break;
+       }
+
+       return 0;
+}      /* isreltime() */
+
+#endif
+
+#ifdef NOT_USED
+int
+dummyfunc()
+{
+       char       *p;
+       char            c;
+       int                     i;
+       char            unit[UNITMAXLEN];
+       char            direction[DIRMAXLEN];
+       int                     localSign;
+       int                     localUnitNumber;
+       long            localQuantity;
+
+       if (!PointerIsValid(sign))
+               sign = &localSign;
+
+       if (!PointerIsValid(unitnr))
+               unitnr = &localUnitNumber;
+
+       if (!PointerIsValid(quantity))
+               quantity = &localQuantity;
+
+       unit[0] = '\0';
+       direction[0] = '\0';
+       p = timestring;
+       /* skip leading blanks */
+       while ((c = *p) != '\0')
+       {
+               if (c != ' ')
+                       break;
+               p++;
+       }
+
+       /* Test whether 'invalid time' identifier or not */
+       if (!strncmp(INVALID_RELTIME_STR, p, strlen(INVALID_RELTIME_STR) + 1))
+               return 2;                               /* correct 'invalid time' identifier found */
+
+       /* handle label of relative time */
+       if (c != RELTIME_LABEL)
+               return 0;                               /* syntax error */
+       c = *++p;
+       if (c != ' ')
+               return 0;                               /* syntax error */
+       p++;
+       /* handle the quantity */
+       *quantity = 0;
+       for (;;)
+       {
+               c = *p;
+               if (isdigit(c))
+               {
+                       *quantity = *quantity * 10 + (c - '0');
+                       p++;
+               }
+               else
+               {
+                       if (c == ' ')
+                               break;                  /* correct quantity found */
+                       else
+                               return 0;               /* syntax error */
+               }
+       }
+
+       /* handle unit */
+       p++;
+       i = 0;
+       for (;;)
+       {
+               c = *p;
+               if (c >= 'a' && c <= 'z' && i <= (UNITMAXLEN - 1))
+               {
+                       unit[i] = c;
+                       p++;
+                       i++;
+               }
+               else
+               {
+                       if ((c == ' ' || c == '\0')
+                               && correct_unit(unit, unitnr))
+                               break;                  /* correct unit found */
+                       else
+                               return 0;               /* syntax error */
+               }
+       }
+
+       /* handle optional direction */
+       if (c == ' ')
+               p++;
+       i = 0;
+       *sign = 1;
+       for (;;)
+       {
+               c = *p;
+               if (c >= 'a' && c <= 'z' && i <= (DIRMAXLEN - 1))
+               {
+                       direction[i] = c;
+                       p++;
+                       i++;
+               }
+               else
+               {
+                       if ((c == ' ' || c == '\0') && i == 0)
+                       {
+                               *sign = 1;
+                               break;                  /* no direction specified */
+                       }
+                       if ((c == ' ' || c == '\0') && i != 0)
+                       {
+                               direction[i] = '\0';
+                               correct_dir(direction, sign);
+                               break;                  /* correct direction found */
+                       }
+                       else
+                               return 0;               /* syntax error */
+               }
+       }
+
+       return 1;
+}
+
+/*
+ *             correct_unit    - returns 1, iff unit is a correct unit description
+ *
+ *             output parameter:
+ *                             unptr: points to an integer which is the appropriate unit number
+ *                                        (see function isreltime())
+ */
+static int
+correct_unit(char *unit, int *unptr)
+{
+       int                     j = 0;
+
+       while (j < NUNITS)
+       {
+               if (strncmp(unit, unit_tab[j], strlen(unit_tab[j])) == 0)
+               {
+                       *unptr = j;
+                       return 1;
+               }
+               j++;
+       }
+       return 0;                                       /* invalid unit descriptor */
+}
+
+/*
+ *             correct_dir             - returns 1, iff direction is a correct identifier
+ *
+ *             output parameter:
+ *                             signptr: points to -1 if dir corresponds to past tense
+ *                                              else  to 1
+ */
+static int
+correct_dir(char *direction, int *signptr)
+{
+       *signptr = 1;
+       if (strncmp(RELTIME_PAST, direction, strlen(RELTIME_PAST) + 1) == 0)
+       {
+               *signptr = -1;
+               return 1;
+       }
+       else
+               return 0;                               /* invalid direction descriptor */
+}
+
+#endif
+
+/*
+ *             istinterval             - returns 1, iff i_string is a valid interval descr.
+ *                                                               0, iff i_string is NOT a valid interval desc.
+ *                                                               2, iff any time is INVALID_ABSTIME
+ *
+ *             output parameter:
+ *                             i_start, i_end: interval margins
+ *
+ *             Time interval:
+ *             `[' {` '} `'' <AbsTime> `'' {` '} `'' <AbsTime> `'' {` '} `]'
+ *
+ *             OR      `Undefined Range'       (see also INVALID_INTERVAL_STR)
+ *
+ *             where <AbsTime> satisfies the syntax of absolute time.
+ *
+ *             e.g.  [  '  Jan 18 1902'   'Jan 1 00:00:00 1970']
+ */
+static int
+istinterval(char *i_string,
+                       AbsoluteTime *i_start,
+                       AbsoluteTime *i_end)
+{
+       char       *p,
+                          *p1;
+       char            c;
+
+       p = i_string;
+       /* skip leading blanks up to '[' */
+       while ((c = *p) != '\0')
+       {
+               if (IsSpace(c))
+                       p++;
+               else if (c != '[')
+                       return 0;                       /* syntax error */
+               else
+                       break;
+       }
+       p++;
+       /* skip leading blanks up to "'" */
+       while ((c = *p) != '\0')
+       {
+               if (IsSpace(c))
+                       p++;
+               else if (c != '"')
+                       return 0;                       /* syntax error */
+               else
+                       break;
+       }
+       p++;
+       if (strncmp(INVALID_INTERVAL_STR, p, strlen(INVALID_INTERVAL_STR)) == 0)
+               return 0;                               /* undefined range, handled like a syntax
+                                                                * err. */
+       /* search for the end of the first date and change it to a NULL */
+       p1 = p;
+       while ((c = *p1) != '\0')
+       {
+               if (c == '"')
+               {
+                       *p1 = '\0';
+                       break;
+               }
+               p1++;
+       }
+       /* get the first date */
+       *i_start = nabstimein(p);       /* first absolute date */
+       /* rechange NULL at the end of the first date to a "'" */
+       *p1 = '"';
+       p = ++p1;
+       /* skip blanks up to "'", beginning of second date */
+       while ((c = *p) != '\0')
+       {
+               if (IsSpace(c))
+                       p++;
+               else if (c != '"')
+                       return 0;                       /* syntax error */
+               else
+                       break;
+       }
+       p++;
+       /* search for the end of the second date and change it to a NULL */
+       p1 = p;
+       while ((c = *p1) != '\0')
+       {
+               if (c == '"')
+               {
+                       *p1 = '\0';
+                       break;
+               }
+               p1++;
+       }
+       /* get the second date */
+       *i_end = nabstimein(p);         /* second absolute date */
+       /* rechange NULL at the end of the first date to a ''' */
+       *p1 = '"';
+       p = ++p1;
+       /* skip blanks up to ']' */
+       while ((c = *p) != '\0')
+       {
+               if (IsSpace(c))
+                       p++;
+               else if (c != ']')
+                       return 0;                       /* syntax error */
+               else
+                       break;
+       }
+       p++;
+       c = *p;
+       if (c != '\0')
+               return 0;                               /* syntax error */
+       /* it seems to be a valid interval */
+       return 1;
+}
+
+
+/*****************************************************************************
+ *
+ *****************************************************************************/
+
+int32                                                  /* RelativeTime */
+int4reltime(int32 timevalue)
+{
+       return timevalue;
+}
+
+/*
+ * timeofday -
+ *        returns the current time as a text. similar to timenow() but returns
+ *        seconds with more precision (up to microsecs). (I need this to compare
+ *        the Wisconsin benchmark with Illustra whose TimeNow() shows current
+ *        time with precision up to microsecs.)                          - ay 3/95
+ */
+text *
+timeofday(void)
+{
+
+       struct timeval tp;
+       struct timezone tpz;
+       char            templ[500];
+       char            buf[500];
+       text       *tm;
+       int                     len = 0;
+
+       gettimeofday(&tp, &tpz);
+       strftime(templ, sizeof(templ), "%a %b %d %H:%M:%S.%%d %Y %Z",
+                        localtime((time_t *) &tp.tv_sec));
+       sprintf(buf, templ, tp.tv_usec);
+
+       len = VARHDRSZ + strlen(buf);
+       tm = (text *) palloc(len);
+       VARSIZE(tm) = len;
+       strncpy(VARDATA(tm), buf, strlen(buf));
+       return tm;
+}
index cdbac4c7f13a6ddf00c647e6f75747aa4cba6cf8..77202c8308ef180de8b1bed1a191b17d2d58cf03 100644 (file)
-#include <time.h>
+/*-------------------------------------------------------------------------
+ *
+ * timestamp.c
+ *       Functions for the built-in SQL92 type "timestamp" and "interval".
+ *
+ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ *       $Header: /cvsroot/pgsql/src/backend/utils/adt/timestamp.c,v 1.22 2000/02/16 17:24:48 thomas Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
 #include <ctype.h>
+#include <math.h>
+#include <sys/types.h>
+#include <errno.h>
 
 #include "postgres.h"
-#include "access/xact.h"
+#ifdef HAVE_FLOAT_H
+#include <float.h>
+#endif
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+#ifndef USE_POSIX_TIME
+#include <sys/timeb.h>
+#endif
+
 #include "miscadmin.h"
 #include "utils/builtins.h"
 
-time_t
-timestamp_in(const char *timestamp_str)
+
+#if 0
+
+
+static int     DecodeDate(char *str, int fmask, int *tmask, struct tm * tm);
+static int DecodeNumber(int flen, char *field,
+       int fmask, int *tmask, struct tm * tm, double *fsec, int *is2digits);
+static int DecodeNumberField(int len, char *str,
+       int fmask, int *tmask, struct tm * tm, double *fsec, int *is2digits);
+static int     DecodeSpecial(int field, char *lowtoken, int *val);
+static int DecodeTime(char *str, int fmask, int *tmask,
+                  struct tm * tm, double *fsec);
+static int     DecodeTimezone(char *str, int *tzp);
+static int     DecodeUnits(int field, char *lowtoken, int *val);
+static int     EncodeSpecialTimestamp(Timestamp dt, char *str);
+static datetkn *datebsearch(char *key, datetkn *base, unsigned int nel);
+static Timestamp dt2local(Timestamp dt, int timezone);
+static int     j2day(int jd);
+static double time2t(const int hour, const int min, const double sec);
+static int     interval2tm(Interval span, struct tm * tm, float8 *fsec);
+static int     tm2interval(struct tm * tm, double fsec, Interval *span);
+
+
+#define USE_DATE_CACHE 1
+#define ROUND_ALL 0
+
+int                    day_tab[2][13] = {
+       {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 0},
+{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 0}};
+
+
+char      *months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
+"Jul", "Aug", "Sep", "Oct", "Nov", "Dec", NULL};
+
+char      *days[] = {"Sunday", "Monday", "Tuesday", "Wednesday",
+"Thursday", "Friday", "Saturday", NULL};
+
+/* TMODULO()
+ * Macro to replace modf(), which is broken on some platforms.
+ */
+#define TMODULO(t,q,u) \
+do { \
+       q = ((t < 0)? ceil(t / u): floor(t / u)); \
+       if (q != 0) \
+               t -= rint(q * u); \
+} while(0)
+
+static void GetEpochTime(struct tm * tm);
+
+#define UTIME_MINYEAR (1901)
+#define UTIME_MINMONTH (12)
+#define UTIME_MINDAY (14)
+#define UTIME_MAXYEAR (2038)
+#define UTIME_MAXMONTH (01)
+#define UTIME_MAXDAY (18)
+
+#define IS_VALID_UTIME(y,m,d) (((y > UTIME_MINYEAR) \
+ || ((y == UTIME_MINYEAR) && ((m > UTIME_MINMONTH) \
+  || ((m == UTIME_MINMONTH) && (d >= UTIME_MINDAY))))) \
+ && ((y < UTIME_MAXYEAR) \
+ || ((y == UTIME_MAXYEAR) && ((m < UTIME_MAXMONTH) \
+  || ((m == UTIME_MAXMONTH) && (d <= UTIME_MAXDAY))))))
+
+
+#endif
+
+
+static double time2t(const int hour, const int min, const double sec);
+
+
+/*****************************************************************************
+ *      USER I/O ROUTINES                                                                                                               *
+ *****************************************************************************/
+
+/* timestamp_in()
+ * Convert a string to internal form.
+ */
+Timestamp   *
+timestamp_in(char *str)
 {
-       int4            result;
+       Timestamp   *result;
+
+       double          fsec;
+       struct tm       tt,
+                          *tm = &tt;
+       int                     tz;
+       int                     dtype;
+       int                     nf;
+       char       *field[MAXDATEFIELDS];
+       int                     ftype[MAXDATEFIELDS];
+       char            lowstr[MAXDATELEN + 1];
+
+       if (!PointerIsValid(str))
+               elog(ERROR, "Bad (null) timestamp external representation");
+
+       if ((ParseDateTime(str, lowstr, field, ftype, MAXDATEFIELDS, &nf) != 0)
+         || (DecodeDateTime(field, ftype, nf, &dtype, tm, &fsec, &tz) != 0))
+               elog(ERROR, "Bad timestamp external representation '%s'", str);
+
+       result = palloc(sizeof(Timestamp));
+
+       switch (dtype)
+       {
+               case DTK_DATE:
+                       if (tm2timestamp(tm, fsec, &tz, result) != 0)
+                               elog(ERROR, "Timestamp out of range '%s'", str);
+                       break;
+
+               case DTK_EPOCH:
+                       TIMESTAMP_EPOCH(*result);
+                       break;
+
+               case DTK_CURRENT:
+                       TIMESTAMP_CURRENT(*result);
+                       break;
+
+               case DTK_LATE:
+                       TIMESTAMP_NOEND(*result);
+                       break;
+
+               case DTK_EARLY:
+                       TIMESTAMP_NOBEGIN(*result);
+                       break;
+
+               case DTK_INVALID:
+                       TIMESTAMP_INVALID(*result);
+                       break;
 
-       result = nabstimein((char *) timestamp_str);
+               default:
+                       elog(ERROR, "Internal coding error, can't input timestamp '%s'", str);
+       }
 
        return result;
-}
+}      /* timestamp_in() */
 
+/* timestamp_out()
+ * Convert a timestamp to external form.
+ */
 char *
-timestamp_out(time_t timestamp)
+timestamp_out(Timestamp *dt)
 {
        char       *result;
        int                     tz;
-       double          fsec = 0;
        struct tm       tt,
                           *tm = &tt;
+       double          fsec;
+       char       *tzn;
        char            buf[MAXDATELEN + 1];
-       char            zone[MAXDATELEN + 1],
-                          *tzn = zone;
 
-       switch (timestamp)
+       if (!PointerIsValid(dt))
+               return NULL;
+
+       if (TIMESTAMP_IS_RESERVED(*dt))
        {
-               case EPOCH_ABSTIME:
-                       strcpy(buf, EPOCH);
-                       break;
-               case INVALID_ABSTIME:
-                       strcpy(buf, INVALID);
-                       break;
-               case CURRENT_ABSTIME:
-                       strcpy(buf, DCURRENT);
-                       break;
-               case NOEND_ABSTIME:
-                       strcpy(buf, LATE);
-                       break;
-               case NOSTART_ABSTIME:
-                       strcpy(buf, EARLY);
+               EncodeSpecialTimestamp(*dt, buf);
+
+       }
+       else if (timestamp2tm(*dt, &tz, tm, &fsec, &tzn) == 0)
+       {
+               EncodeDateTime(tm, fsec, &tz, &tzn, DateStyle, buf);
+
+       }
+       else
+               EncodeSpecialTimestamp(DT_INVALID, buf);
+
+       result = palloc(strlen(buf) + 1);
+
+       strcpy(result, buf);
+
+       return result;
+}      /* timestamp_out() */
+
+
+/* interval_in()
+ * Convert a string to internal form.
+ *
+ * External format(s):
+ *     Uses the generic date/time parsing and decoding routines.
+ */
+Interval   *
+interval_in(char *str)
+{
+       Interval   *span;
+
+       double          fsec;
+       struct tm       tt,
+                          *tm = &tt;
+       int                     dtype;
+       int                     nf;
+       char       *field[MAXDATEFIELDS];
+       int                     ftype[MAXDATEFIELDS];
+       char            lowstr[MAXDATELEN + 1];
+
+       tm->tm_year = 0;
+       tm->tm_mon = 0;
+       tm->tm_mday = 0;
+       tm->tm_hour = 0;
+       tm->tm_min = 0;
+       tm->tm_sec = 0;
+       fsec = 0;
+
+       if (!PointerIsValid(str))
+               elog(ERROR, "Bad (null) interval external representation");
+
+       if ((ParseDateTime(str, lowstr, field, ftype, MAXDATEFIELDS, &nf) != 0)
+               || (DecodeDateDelta(field, ftype, nf, &dtype, tm, &fsec) != 0))
+               elog(ERROR, "Bad interval external representation '%s'", str);
+
+       span = palloc(sizeof(Interval));
+
+       switch (dtype)
+       {
+               case DTK_DELTA:
+                       if (tm2interval(tm, fsec, span) != 0)
+                       {
+#if NOT_USED
+                               INTERVAL_INVALID(span);
+#endif
+                               elog(ERROR, "Bad interval external representation '%s'", str);
+                       }
                        break;
+
                default:
-                       abstime2tm(timestamp, &tz, tm, tzn);
-                       EncodeDateTime(tm, fsec, &tz, &tzn, USE_ISO_DATES, buf);
-                       break;
+                       elog(ERROR, "Internal coding error, can't input interval '%s'", str);
        }
 
+       return span;
+}      /* interval_in() */
+
+/* interval_out()
+ * Convert a time span to external form.
+ */
+char *
+interval_out(Interval *span)
+{
+       char       *result;
+
+       struct tm       tt,
+                          *tm = &tt;
+       double          fsec;
+       char            buf[MAXDATELEN + 1];
+
+       if (!PointerIsValid(span))
+               return NULL;
+
+       if (interval2tm(*span, tm, &fsec) != 0)
+               return NULL;
+
+       if (EncodeTimeSpan(tm, fsec, DateStyle, buf) != 0)
+               elog(ERROR, "Unable to format interval");
+
        result = palloc(strlen(buf) + 1);
+
        strcpy(result, buf);
        return result;
-}      /* timestamp_out() */
+}      /* interval_out() */
+
+
+/* EncodeSpecialTimestamp()
+ * Convert reserved timestamp data type to string.
+ */
+int
+EncodeSpecialTimestamp(Timestamp dt, char *str)
+{
+       if (TIMESTAMP_IS_RESERVED(dt))
+       {
+               if (TIMESTAMP_IS_INVALID(dt))
+                       strcpy(str, INVALID);
+               else if (TIMESTAMP_IS_NOBEGIN(dt))
+                       strcpy(str, EARLY);
+               else if (TIMESTAMP_IS_NOEND(dt))
+                       strcpy(str, LATE);
+               else if (TIMESTAMP_IS_CURRENT(dt))
+                       strcpy(str, DCURRENT);
+               else if (TIMESTAMP_IS_EPOCH(dt))
+                       strcpy(str, EPOCH);
+               else
+                       strcpy(str, INVALID);
+               return TRUE;
+       }
 
-time_t
+       return FALSE;
+}      /* EncodeSpecialTimestamp() */
+
+Timestamp *
 now(void)
 {
-       time_t          sec;
+       Timestamp *result;
+       AbsoluteTime sec;
+
+       result = palloc(sizeof(Timestamp));
 
        sec = GetCurrentTransactionStartTime();
-       return sec;
+
+       *result = (sec - ((date2j(2000, 1, 1) - date2j(1970, 1, 1)) * 86400));
+
+       return result;
 }
 
+void
+dt2time(Timestamp jd, int *hour, int *min, double *sec)
+{
+       double          time;
+
+       time = jd;
+
+       *hour = (time / 3600);
+       time -= ((*hour) * 3600);
+       *min = (time / 60);
+       time -= ((*min) * 60);
+       *sec = JROUND(time);
+
+       return;
+}      /* dt2time() */
+
+
+/* timestamp2tm()
+ * Convert timestamp data type to POSIX time structure.
+ * Note that year is _not_ 1900-based, but is an explicit full value.
+ * Also, month is one-based, _not_ zero-based.
+ * Returns:
+ *      0 on success
+ *     -1 on out of range
+ *
+ * For dates within the system-supported time_t range, convert to the
+ *     local time zone. If out of this range, leave as GMT. - tgl 97/05/27
+ */
+int
+timestamp2tm(Timestamp dt, int *tzp, struct tm * tm, double *fsec, char **tzn)
+{
+       double          date,
+                               date0,
+                               time,
+                               sec;
+       time_t          utime;
+
+#ifdef USE_POSIX_TIME
+       struct tm  *tx;
+
+#endif
+
+       date0 = date2j(2000, 1, 1);
+
+       time = dt;
+       TMODULO(time, date, 86400e0);
+
+       if (time < 0)
+       {
+               time += 86400;
+               date -= 1;
+       }
+
+       /* Julian day routine does not work for negative Julian days */
+       if (date < -date0)
+               return -1;
+
+       /* add offset to go from J2000 back to standard Julian date */
+       date += date0;
+
+       j2date((int) date, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
+       dt2time(time, &tm->tm_hour, &tm->tm_min, &sec);
+
+       *fsec = JROUND(sec);
+       TMODULO(*fsec, tm->tm_sec, 1e0);
+
+       if (tzp != NULL)
+       {
+               if (IS_VALID_UTIME(tm->tm_year, tm->tm_mon, tm->tm_mday))
+               {
+                       utime = (dt + (date0 - date2j(1970, 1, 1)) * 86400);
+
+#ifdef USE_POSIX_TIME
+                       tx = localtime(&utime);
+                       tm->tm_year = tx->tm_year + 1900;
+                       tm->tm_mon = tx->tm_mon + 1;
+                       tm->tm_mday = tx->tm_mday;
+                       tm->tm_hour = tx->tm_hour;
+                       tm->tm_min = tx->tm_min;
+#if NOT_USED
+/* XXX HACK
+ * Argh! My Linux box puts in a 1 second offset for dates less than 1970
+ *     but only if the seconds field was non-zero. So, don't copy the seconds
+ *     field and instead carry forward from the original - tgl 97/06/18
+ * Note that GNU/Linux uses the standard freeware zic package as do
+ *     many other platforms so this may not be GNU/Linux/ix86-specific.
+ */
+                       tm->tm_sec = tx->tm_sec;
+#endif
+                       tm->tm_isdst = tx->tm_isdst;
+
+#if defined(HAVE_TM_ZONE)
+                       tm->tm_gmtoff = tx->tm_gmtoff;
+                       tm->tm_zone = tx->tm_zone;
+
+                       *tzp = -(tm->tm_gmtoff);        /* tm_gmtoff is Sun/DEC-ism */
+                       if (tzn != NULL)
+                               *tzn = (char *) tm->tm_zone;
+#elif defined(HAVE_INT_TIMEZONE)
+#ifdef __CYGWIN__
+                       *tzp = (tm->tm_isdst ? (_timezone - 3600) : _timezone);
+#else
+                       *tzp = (tm->tm_isdst ? (timezone - 3600) : timezone);
+#endif
+                       if (tzn != NULL)
+                               *tzn = tzname[(tm->tm_isdst > 0)];
+#else
+#error USE_POSIX_TIME is defined but neither HAVE_TM_ZONE or HAVE_INT_TIMEZONE are defined
+#endif
+
+#else                                                  /* !USE_POSIX_TIME */
+                       *tzp = CTimeZone;       /* V7 conventions; don't know timezone? */
+                       if (tzn != NULL)
+                               *tzn = CTZName;
+#endif
+
+               }
+               else
+               {
+                       *tzp = 0;
+                       tm->tm_isdst = 0;
+                       if (tzn != NULL)
+                               *tzn = NULL;
+               }
+
+               dt = dt2local(dt, *tzp);
+
+       }
+       else
+       {
+               tm->tm_isdst = 0;
+               if (tzn != NULL)
+                       *tzn = NULL;
+       }
+
+       return 0;
+}      /* timestamp2tm() */
+
+
+/* tm2timestamp()
+ * Convert a tm structure to a timestamp data type.
+ * Note that year is _not_ 1900-based, but is an explicit full value.
+ * Also, month is one-based, _not_ zero-based.
+ */
+int
+tm2timestamp(struct tm * tm, double fsec, int *tzp, Timestamp *result)
+{
+
+       double          date,
+                               time;
+
+       /* Julian day routines are not correct for negative Julian days */
+       if (!IS_VALID_JULIAN(tm->tm_year, tm->tm_mon, tm->tm_mday))
+               return -1;
+
+       date = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - date2j(2000, 1, 1);
+       time = time2t(tm->tm_hour, tm->tm_min, (tm->tm_sec + fsec));
+       *result = (date * 86400 + time);
+       if (tzp != NULL)
+               *result = dt2local(*result, -(*tzp));
+
+       return 0;
+}      /* tm2timestamp() */
+
+
+/* interval2tm()
+ * Convert a interval data type to a tm structure.
+ */
+int
+interval2tm(Interval span, struct tm * tm, float8 *fsec)
+{
+       double          time;
+
+       if (span.month != 0)
+       {
+               tm->tm_year = span.month / 12;
+               tm->tm_mon = span.month % 12;
+
+       }
+       else
+       {
+               tm->tm_year = 0;
+               tm->tm_mon = 0;
+       }
+
+#ifdef ROUND_ALL
+       time = JROUND(span.time);
+#else
+       time = span.time;
+#endif
+
+       TMODULO(time, tm->tm_mday, 86400e0);
+       TMODULO(time, tm->tm_hour, 3600e0);
+       TMODULO(time, tm->tm_min, 60e0);
+       TMODULO(time, tm->tm_sec, 1e0);
+       *fsec = time;
+
+       return 0;
+}      /* interval2tm() */
+
+int
+tm2interval(struct tm * tm, double fsec, Interval *span)
+{
+       span->month = ((tm->tm_year * 12) + tm->tm_mon);
+       span->time = ((((((tm->tm_mday * 24.0)
+                                        + tm->tm_hour) * 60.0)
+                                        + tm->tm_min) * 60.0)
+                                        + tm->tm_sec);
+       span->time = JROUND(span->time + fsec);
+
+       return 0;
+}      /* tm2interval() */
+
+static double
+time2t(const int hour, const int min, const double sec)
+{
+       return (((hour * 60) + min) * 60) + sec;
+}      /* time2t() */
+
+Timestamp
+dt2local(Timestamp dt, int tz)
+{
+       dt -= tz;
+       dt = JROUND(dt);
+       return dt;
+}      /* dt2local() */
+
+
+/*****************************************************************************
+ *      PUBLIC ROUTINES                                                                                                                 *
+ *****************************************************************************/
+
+
 bool
-timestampeq(time_t t1, time_t t2)
+timestamp_finite(Timestamp *timestamp)
 {
-       return abstimeeq(t1, t2);
-}
+       if (!PointerIsValid(timestamp))
+               return FALSE;
+
+       return !TIMESTAMP_NOT_FINITE(*timestamp);
+}      /* timestamp_finite() */
 
 bool
-timestampne(time_t t1, time_t t2)
+interval_finite(Interval *interval)
 {
-       return abstimene(t1, t2);
-}
+       if (!PointerIsValid(interval))
+               return FALSE;
+
+       return !INTERVAL_NOT_FINITE(*interval);
+}      /* interval_finite() */
+
+
+/*----------------------------------------------------------
+ *     Relational operators for timestamp.
+ *---------------------------------------------------------*/
+
+static void
+GetEpochTime(struct tm * tm)
+{
+       struct tm  *t0;
+       time_t          epoch = 0;
+
+       t0 = gmtime(&epoch);
+
+       tm->tm_year = t0->tm_year;
+       tm->tm_mon = t0->tm_mon;
+       tm->tm_mday = t0->tm_mday;
+       tm->tm_hour = t0->tm_hour;
+       tm->tm_min = t0->tm_min;
+       tm->tm_sec = t0->tm_sec;
+
+       if (tm->tm_year < 1900)
+               tm->tm_year += 1900;
+       tm->tm_mon++;
+
+       return;
+}      /* GetEpochTime() */
+
+Timestamp
+SetTimestamp(Timestamp dt)
+{
+       struct tm       tt;
+
+       if (TIMESTAMP_IS_CURRENT(dt))
+       {
+               GetCurrentTime(&tt);
+               tm2timestamp(&tt, 0, NULL, &dt);
+               dt = dt2local(dt, -CTimeZone);
+       }
+       else
+       {                                                       /* if (TIMESTAMP_IS_EPOCH(dt1)) */
+               GetEpochTime(&tt);
+               tm2timestamp(&tt, 0, NULL, &dt);
+       }
 
+       return dt;
+}      /* SetTimestamp() */
+
+/*             timestamp_relop - is timestamp1 relop timestamp2
+ */
 bool
-timestamplt(time_t t1, time_t t2)
+timestamp_eq(Timestamp *timestamp1, Timestamp *timestamp2)
 {
-       return abstimelt(t1, t2);
-}
+       Timestamp       dt1,
+                               dt2;
+
+       if (!PointerIsValid(timestamp1) || !PointerIsValid(timestamp2))
+               return FALSE;
+
+       dt1 = *timestamp1;
+       dt2 = *timestamp2;
+
+       if (TIMESTAMP_IS_INVALID(dt1) || TIMESTAMP_IS_INVALID(dt2))
+               return FALSE;
+
+       if (TIMESTAMP_IS_RELATIVE(dt1))
+               dt1 = SetTimestamp(dt1);
+       if (TIMESTAMP_IS_RELATIVE(dt2))
+               dt2 = SetTimestamp(dt2);
+
+       return dt1 == dt2;
+}      /* timestamp_eq() */
 
 bool
-timestampgt(time_t t1, time_t t2)
+timestamp_ne(Timestamp *timestamp1, Timestamp *timestamp2)
 {
-       return abstimegt(t1, t2);
-}
+       Timestamp       dt1,
+                               dt2;
+
+       if (!PointerIsValid(timestamp1) || !PointerIsValid(timestamp2))
+               return FALSE;
+
+       dt1 = *timestamp1;
+       dt2 = *timestamp2;
+
+       if (TIMESTAMP_IS_INVALID(dt1) || TIMESTAMP_IS_INVALID(dt2))
+               return FALSE;
+
+       if (TIMESTAMP_IS_RELATIVE(dt1))
+               dt1 = SetTimestamp(dt1);
+       if (TIMESTAMP_IS_RELATIVE(dt2))
+               dt2 = SetTimestamp(dt2);
+
+       return dt1 != dt2;
+}      /* timestamp_ne() */
 
 bool
-timestample(time_t t1, time_t t2)
+timestamp_lt(Timestamp *timestamp1, Timestamp *timestamp2)
 {
-       return abstimele(t1, t2);
-}
+       Timestamp       dt1,
+                               dt2;
+
+       if (!PointerIsValid(timestamp1) || !PointerIsValid(timestamp2))
+               return FALSE;
+
+       dt1 = *timestamp1;
+       dt2 = *timestamp2;
+
+       if (TIMESTAMP_IS_INVALID(dt1) || TIMESTAMP_IS_INVALID(dt2))
+               return FALSE;
+
+       if (TIMESTAMP_IS_RELATIVE(dt1))
+               dt1 = SetTimestamp(dt1);
+       if (TIMESTAMP_IS_RELATIVE(dt2))
+               dt2 = SetTimestamp(dt2);
+
+       return dt1 < dt2;
+}      /* timestamp_lt() */
 
 bool
-timestampge(time_t t1, time_t t2)
+timestamp_gt(Timestamp *timestamp1, Timestamp *timestamp2)
 {
-       return abstimege(t1, t2);
-}
+       Timestamp       dt1,
+                               dt2;
+
+       if (!PointerIsValid(timestamp1) || !PointerIsValid(timestamp2))
+               return FALSE;
+
+       dt1 = *timestamp1;
+       dt2 = *timestamp2;
+
+       if (TIMESTAMP_IS_INVALID(dt1) || TIMESTAMP_IS_INVALID(dt2))
+               return FALSE;
+
+       if (TIMESTAMP_IS_RELATIVE(dt1))
+               dt1 = SetTimestamp(dt1);
+       if (TIMESTAMP_IS_RELATIVE(dt2))
+               dt2 = SetTimestamp(dt2);
+
+       return dt1 > dt2;
+}      /* timestamp_gt() */
+
+bool
+timestamp_le(Timestamp *timestamp1, Timestamp *timestamp2)
+{
+       Timestamp       dt1,
+                               dt2;
+
+       if (!PointerIsValid(timestamp1) || !PointerIsValid(timestamp2))
+               return FALSE;
+
+       dt1 = *timestamp1;
+       dt2 = *timestamp2;
+
+       if (TIMESTAMP_IS_INVALID(dt1) || TIMESTAMP_IS_INVALID(dt2))
+               return FALSE;
+
+       if (TIMESTAMP_IS_RELATIVE(dt1))
+               dt1 = SetTimestamp(dt1);
+       if (TIMESTAMP_IS_RELATIVE(dt2))
+               dt2 = SetTimestamp(dt2);
+
+       return dt1 <= dt2;
+}      /* timestamp_le() */
+
+bool
+timestamp_ge(Timestamp *timestamp1, Timestamp *timestamp2)
+{
+       Timestamp       dt1,
+                               dt2;
+
+       if (!PointerIsValid(timestamp1) || !PointerIsValid(timestamp2))
+               return FALSE;
+
+       dt1 = *timestamp1;
+       dt2 = *timestamp2;
+
+       if (TIMESTAMP_IS_INVALID(dt1) || TIMESTAMP_IS_INVALID(dt2))
+               return FALSE;
+
+       if (TIMESTAMP_IS_RELATIVE(dt1))
+               dt1 = SetTimestamp(dt1);
+       if (TIMESTAMP_IS_RELATIVE(dt2))
+               dt2 = SetTimestamp(dt2);
+
+       return dt1 >= dt2;
+}      /* timestamp_ge() */
+
+
+/*             timestamp_cmp   - 3-state comparison for timestamp
+ *             collate invalid timestamp at the end
+ */
+int
+timestamp_cmp(Timestamp *timestamp1, Timestamp *timestamp2)
+{
+       Timestamp       dt1,
+                               dt2;
+
+       if (!PointerIsValid(timestamp1) || !PointerIsValid(timestamp2))
+               return 0;
+
+       dt1 = *timestamp1;
+       dt2 = *timestamp2;
 
-DateTime   *
-timestamp_datetime(time_t timestamp)
+       if (TIMESTAMP_IS_INVALID(dt1))
+       {
+               return (TIMESTAMP_IS_INVALID(dt2) ? 0 : 1);
+
+       }
+       else if (TIMESTAMP_IS_INVALID(dt2))
+       {
+               return -1;
+
+       }
+       else
+       {
+               if (TIMESTAMP_IS_RELATIVE(dt1))
+                       dt1 = SetTimestamp(dt1);
+               if (TIMESTAMP_IS_RELATIVE(dt2))
+                       dt2 = SetTimestamp(dt2);
+       }
+
+       return ((dt1 < dt2) ? -1 : ((dt1 > dt2) ? 1 : 0));
+}      /* timestamp_cmp() */
+
+
+/*             interval_relop  - is interval1 relop interval2
+ */
+bool
+interval_eq(Interval *interval1, Interval *interval2)
+{
+       if (!PointerIsValid(interval1) || !PointerIsValid(interval2))
+               return FALSE;
+
+       if (INTERVAL_IS_INVALID(*interval1) || INTERVAL_IS_INVALID(*interval2))
+               return FALSE;
+
+       return ((interval1->time == interval2->time)
+                       && (interval1->month == interval2->month));
+}      /* interval_eq() */
+
+bool
+interval_ne(Interval *interval1, Interval *interval2)
+{
+       if (!PointerIsValid(interval1) || !PointerIsValid(interval2))
+               return FALSE;
+
+       if (INTERVAL_IS_INVALID(*interval1) || INTERVAL_IS_INVALID(*interval2))
+               return FALSE;
+
+       return ((interval1->time != interval2->time)
+                       || (interval1->month != interval2->month));
+}      /* interval_ne() */
+
+bool
+interval_lt(Interval *interval1, Interval *interval2)
 {
-       return abstime_datetime((AbsoluteTime) timestamp);
-}      /* timestamp_datetime() */
+       double          span1,
+                               span2;
+
+       if (!PointerIsValid(interval1) || !PointerIsValid(interval2))
+               return FALSE;
+
+       if (INTERVAL_IS_INVALID(*interval1) || INTERVAL_IS_INVALID(*interval2))
+               return FALSE;
 
-time_t
-datetime_timestamp(DateTime *datetime)
+       span1 = interval1->time;
+       if (interval1->month != 0)
+               span1 += (interval1->month * (30.0 * 86400));
+       span2 = interval2->time;
+       if (interval2->month != 0)
+               span2 += (interval2->month * (30.0 * 86400));
+
+       return span1 < span2;
+}      /* interval_lt() */
+
+bool
+interval_gt(Interval *interval1, Interval *interval2)
 {
-       return (AbsoluteTime) datetime_abstime(datetime);
-}      /* datetime_timestamp() */
+       double          span1,
+                               span2;
+
+       if (!PointerIsValid(interval1) || !PointerIsValid(interval2))
+               return FALSE;
+
+       if (INTERVAL_IS_INVALID(*interval1) || INTERVAL_IS_INVALID(*interval2))
+               return FALSE;
+
+       span1 = interval1->time;
+       if (interval1->month != 0)
+               span1 += (interval1->month * (30.0 * 86400));
+       span2 = interval2->time;
+       if (interval2->month != 0)
+               span2 += (interval2->month * (30.0 * 86400));
+
+       return span1 > span2;
+}      /* interval_gt() */
+
+bool
+interval_le(Interval *interval1, Interval *interval2)
+{
+       double          span1,
+                               span2;
+
+       if (!PointerIsValid(interval1) || !PointerIsValid(interval2))
+               return FALSE;
+
+       if (INTERVAL_IS_INVALID(*interval1) || INTERVAL_IS_INVALID(*interval2))
+               return FALSE;
+
+       span1 = interval1->time;
+       if (interval1->month != 0)
+               span1 += (interval1->month * (30.0 * 86400));
+       span2 = interval2->time;
+       if (interval2->month != 0)
+               span2 += (interval2->month * (30.0 * 86400));
+
+       return span1 <= span2;
+}      /* interval_le() */
+
+bool
+interval_ge(Interval *interval1, Interval *interval2)
+{
+       double          span1,
+                               span2;
+
+       if (!PointerIsValid(interval1) || !PointerIsValid(interval2))
+               return FALSE;
+
+       if (INTERVAL_IS_INVALID(*interval1) || INTERVAL_IS_INVALID(*interval2))
+               return FALSE;
+
+       span1 = interval1->time;
+       if (interval1->month != 0)
+               span1 += (interval1->month * (30.0 * 86400));
+       span2 = interval2->time;
+       if (interval2->month != 0)
+               span2 += (interval2->month * (30.0 * 86400));
+
+       return span1 >= span2;
+}      /* interval_ge() */
+
+
+/*             interval_cmp    - 3-state comparison for interval
+ */
+int
+interval_cmp(Interval *interval1, Interval *interval2)
+{
+       double          span1,
+                               span2;
+
+       if (!PointerIsValid(interval1) || !PointerIsValid(interval2))
+               return 0;
+
+       if (INTERVAL_IS_INVALID(*interval1))
+       {
+               return INTERVAL_IS_INVALID(*interval2) ? 0 : 1;
+
+       }
+       else if (INTERVAL_IS_INVALID(*interval2))
+               return -1;
+
+       span1 = interval1->time;
+       if (interval1->month != 0)
+               span1 += (interval1->month * (30.0 * 86400));
+       span2 = interval2->time;
+       if (interval2->month != 0)
+               span2 += (interval2->month * (30.0 * 86400));
+
+       return (span1 < span2) ? -1 : (span1 > span2) ? 1 : 0;
+}      /* interval_cmp() */
+
+
+/*----------------------------------------------------------
+ *     "Arithmetic" operators on date/times.
+ *             timestamp_foo   returns foo as an object (pointer) that
+ *                                             can be passed between languages.
+ *             timestamp_xx            is an internal routine which returns the
+ *                                             actual value.
+ *---------------------------------------------------------*/
+
+Timestamp   *
+timestamp_smaller(Timestamp *timestamp1, Timestamp *timestamp2)
+{
+       Timestamp   *result;
+
+       Timestamp       dt1,
+                               dt2;
+
+       if (!PointerIsValid(timestamp1) || !PointerIsValid(timestamp2))
+               return NULL;
+
+       dt1 = *timestamp1;
+       dt2 = *timestamp2;
+
+       result = palloc(sizeof(Timestamp));
+
+       if (TIMESTAMP_IS_RELATIVE(dt1))
+               dt1 = SetTimestamp(dt1);
+       if (TIMESTAMP_IS_RELATIVE(dt2))
+               dt2 = SetTimestamp(dt2);
+
+       if (TIMESTAMP_IS_INVALID(dt1))
+               *result = dt2;
+       else if (TIMESTAMP_IS_INVALID(dt2))
+               *result = dt1;
+       else
+               *result = ((dt2 < dt1) ? dt2 : dt1);
+
+       return result;
+}      /* timestamp_smaller() */
+
+Timestamp   *
+timestamp_larger(Timestamp *timestamp1, Timestamp *timestamp2)
+{
+       Timestamp   *result;
+
+       Timestamp       dt1,
+                               dt2;
+
+       if (!PointerIsValid(timestamp1) || !PointerIsValid(timestamp2))
+               return NULL;
+
+       dt1 = *timestamp1;
+       dt2 = *timestamp2;
+
+       result = palloc(sizeof(Timestamp));
+
+       if (TIMESTAMP_IS_RELATIVE(dt1))
+               dt1 = SetTimestamp(dt1);
+       if (TIMESTAMP_IS_RELATIVE(dt2))
+               dt2 = SetTimestamp(dt2);
+
+       if (TIMESTAMP_IS_INVALID(dt1))
+               *result = dt2;
+       else if (TIMESTAMP_IS_INVALID(dt2))
+               *result = dt1;
+       else
+               *result = ((dt2 > dt1) ? dt2 : dt1);
+
+       return result;
+}      /* timestamp_larger() */
+
+
+Interval   *
+timestamp_mi(Timestamp *timestamp1, Timestamp *timestamp2)
+{
+       Interval   *result;
+
+       Timestamp       dt1,
+                               dt2;
+
+       if (!PointerIsValid(timestamp1) || !PointerIsValid(timestamp2))
+               return NULL;
+
+       dt1 = *timestamp1;
+       dt2 = *timestamp2;
+
+       result = palloc(sizeof(Interval));
+
+       if (TIMESTAMP_IS_RELATIVE(dt1))
+               dt1 = SetTimestamp(dt1);
+       if (TIMESTAMP_IS_RELATIVE(dt2))
+               dt2 = SetTimestamp(dt2);
+
+       if (TIMESTAMP_IS_INVALID(dt1)
+               || TIMESTAMP_IS_INVALID(dt2))
+       {
+               TIMESTAMP_INVALID(result->time);
+
+       }
+       else
+               result->time = JROUND(dt1 - dt2);
+       result->month = 0;
+
+       return result;
+}      /* timestamp_mi() */
+
+
+/* timestamp_pl_span()
+ * Add a interval to a timestamp data type.
+ * Note that interval has provisions for qualitative year/month
+ *     units, so try to do the right thing with them.
+ * To add a month, increment the month, and use the same day of month.
+ * Then, if the next month has fewer days, set the day of month
+ *     to the last day of month.
+ * Lastly, add in the "quantitative time".
+ */
+Timestamp   *
+timestamp_pl_span(Timestamp *timestamp, Interval *span)
+{
+       Timestamp   *result;
+       Timestamp       dt;
+       int                     tz;
+       char       *tzn;
+
+       if ((!PointerIsValid(timestamp)) || (!PointerIsValid(span)))
+               return NULL;
+
+       result = palloc(sizeof(Timestamp));
+
+       if (TIMESTAMP_NOT_FINITE(*timestamp))
+       {
+               *result = *timestamp;
+
+       }
+       else if (INTERVAL_IS_INVALID(*span))
+       {
+               TIMESTAMP_INVALID(*result);
+
+       }
+       else
+       {
+               dt = (TIMESTAMP_IS_RELATIVE(*timestamp) ? SetTimestamp(*timestamp) : *timestamp);
+
+               if (span->month != 0)
+               {
+                       struct tm       tt,
+                                          *tm = &tt;
+                       double          fsec;
+
+                       if (timestamp2tm(dt, &tz, tm, &fsec, &tzn) == 0)
+                       {
+                               tm->tm_mon += span->month;
+                               if (tm->tm_mon > 12)
+                               {
+                                       tm->tm_year += ((tm->tm_mon - 1) / 12);
+                                       tm->tm_mon = (((tm->tm_mon - 1) % 12) + 1);
+                               }
+                               else if (tm->tm_mon < 1)
+                               {
+                                       tm->tm_year += ((tm->tm_mon / 12) - 1);
+                                       tm->tm_mon = ((tm->tm_mon % 12) + 12);
+                               }
+
+                               /* adjust for end of month boundary problems... */
+                               if (tm->tm_mday > day_tab[isleap(tm->tm_year)][tm->tm_mon - 1])
+                                       tm->tm_mday = (day_tab[isleap(tm->tm_year)][tm->tm_mon - 1]);
+
+                               if (tm2timestamp(tm, fsec, &tz, &dt) != 0)
+                                       elog(ERROR, "Unable to add timestamp and interval");
+
+                       }
+                       else
+                               TIMESTAMP_INVALID(dt);
+               }
+
+#ifdef ROUND_ALL
+               dt = JROUND(dt + span->time);
+#else
+               dt += span->time;
+#endif
+
+               *result = dt;
+       }
+
+       return result;
+}      /* timestamp_pl_span() */
+
+Timestamp   *
+timestamp_mi_span(Timestamp *timestamp, Interval *span)
+{
+       Timestamp   *result;
+       Interval        tspan;
+
+       if (!PointerIsValid(timestamp) || !PointerIsValid(span))
+               return NULL;
+
+       tspan.month = -span->month;
+       tspan.time = -span->time;
+
+       result = timestamp_pl_span(timestamp, &tspan);
+
+       return result;
+}      /* timestamp_mi_span() */
+
+
+Interval   *
+interval_um(Interval *interval)
+{
+       Interval   *result;
+
+       if (!PointerIsValid(interval))
+               return NULL;
+
+       result = palloc(sizeof(Interval));
+
+       result->time = -(interval->time);
+       result->month = -(interval->month);
+
+       return result;
+}      /* interval_um() */
+
+
+Interval   *
+interval_smaller(Interval *interval1, Interval *interval2)
+{
+       Interval   *result;
+
+       double          span1,
+                               span2;
+
+       if (!PointerIsValid(interval1) || !PointerIsValid(interval2))
+               return NULL;
+
+       result = palloc(sizeof(Interval));
+
+       if (INTERVAL_IS_INVALID(*interval1))
+       {
+               result->time = interval2->time;
+               result->month = interval2->month;
+
+       }
+       else if (INTERVAL_IS_INVALID(*interval2))
+       {
+               result->time = interval1->time;
+               result->month = interval1->month;
+
+       }
+       else
+       {
+               span1 = interval1->time;
+               if (interval1->month != 0)
+                       span1 += (interval1->month * (30.0 * 86400));
+               span2 = interval2->time;
+               if (interval2->month != 0)
+                       span2 += (interval2->month * (30.0 * 86400));
+
+               if (span2 < span1)
+               {
+                       result->time = interval2->time;
+                       result->month = interval2->month;
+
+               }
+               else
+               {
+                       result->time = interval1->time;
+                       result->month = interval1->month;
+               }
+       }
+
+       return result;
+}      /* interval_smaller() */
+
+Interval   *
+interval_larger(Interval *interval1, Interval *interval2)
+{
+       Interval   *result;
+
+       double          span1,
+                               span2;
+
+       if (!PointerIsValid(interval1) || !PointerIsValid(interval2))
+               return NULL;
+
+       result = palloc(sizeof(Interval));
+
+       if (INTERVAL_IS_INVALID(*interval1))
+       {
+               result->time = interval2->time;
+               result->month = interval2->month;
+
+       }
+       else if (INTERVAL_IS_INVALID(*interval2))
+       {
+               result->time = interval1->time;
+               result->month = interval1->month;
+
+       }
+       else
+       {
+               span1 = interval1->time;
+               if (interval1->month != 0)
+                       span1 += (interval1->month * (30.0 * 86400));
+               span2 = interval2->time;
+               if (interval2->month != 0)
+                       span2 += (interval2->month * (30.0 * 86400));
+
+               if (span2 > span1)
+               {
+                       result->time = interval2->time;
+                       result->month = interval2->month;
+
+               }
+               else
+               {
+                       result->time = interval1->time;
+                       result->month = interval1->month;
+               }
+       }
+
+       return result;
+}      /* interval_larger() */
+
+
+Interval   *
+interval_pl(Interval *span1, Interval *span2)
+{
+       Interval   *result;
+
+       if ((!PointerIsValid(span1)) || (!PointerIsValid(span2)))
+               return NULL;
+
+       result = palloc(sizeof(Interval));
+
+       result->month = (span1->month + span2->month);
+       result->time = JROUND(span1->time + span2->time);
+
+       return result;
+}      /* interval_pl() */
+
+Interval   *
+interval_mi(Interval *span1, Interval *span2)
+{
+       Interval   *result;
+
+       if ((!PointerIsValid(span1)) || (!PointerIsValid(span2)))
+               return NULL;
+
+       result = palloc(sizeof(Interval));
+
+       result->month = (span1->month - span2->month);
+       result->time = JROUND(span1->time - span2->time);
+
+       return result;
+}      /* interval_mi() */
+
+Interval   *
+interval_div(Interval *span1, float8 *arg2)
+{
+       Interval   *result;
+
+       if ((!PointerIsValid(span1)) || (!PointerIsValid(arg2)))
+               return NULL;
+
+       if (!PointerIsValid(result = palloc(sizeof(Interval))))
+               elog(ERROR, "Memory allocation failed, can't divide intervals");
+
+       if (*arg2 == 0.0)
+               elog(ERROR, "interval_div:  divide by 0.0 error");
+
+       result->month = rint(span1->month / *arg2);
+       result->time = JROUND(span1->time / *arg2);
+
+       return result;
+}      /* interval_div() */
+
+/* timestamp_age()
+ * Calculate time difference while retaining year/month fields.
+ * Note that this does not result in an accurate absolute time span
+ *     since year and month are out of context once the arithmetic
+ *     is done.
+ */
+Interval   *
+timestamp_age(Timestamp *timestamp1, Timestamp *timestamp2)
+{
+       Interval   *result;
+
+       Timestamp       dt1,
+                               dt2;
+       double          fsec,
+                               fsec1,
+                               fsec2;
+       struct tm       tt,
+                          *tm = &tt;
+       struct tm       tt1,
+                          *tm1 = &tt1;
+       struct tm       tt2,
+                          *tm2 = &tt2;
+
+       if (!PointerIsValid(timestamp1) || !PointerIsValid(timestamp2))
+               return NULL;
+
+       result = palloc(sizeof(Interval));
+
+       dt1 = *timestamp1;
+       dt2 = *timestamp2;
+
+       if (TIMESTAMP_IS_RELATIVE(dt1))
+               dt1 = SetTimestamp(dt1);
+       if (TIMESTAMP_IS_RELATIVE(dt2))
+               dt2 = SetTimestamp(dt2);
+
+       if (TIMESTAMP_IS_INVALID(dt1)
+               || TIMESTAMP_IS_INVALID(dt2))
+       {
+               TIMESTAMP_INVALID(result->time);
+
+       }
+       else if ((timestamp2tm(dt1, NULL, tm1, &fsec1, NULL) == 0)
+                        && (timestamp2tm(dt2, NULL, tm2, &fsec2, 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);
+               tm->tm_mday = (tm1->tm_mday - tm2->tm_mday);
+               tm->tm_mon = (tm1->tm_mon - tm2->tm_mon);
+               tm->tm_year = (tm1->tm_year - tm2->tm_year);
+
+               /* flip sign if necessary... */
+               if (dt1 < dt2)
+               {
+                       fsec = -fsec;
+                       tm->tm_sec = -tm->tm_sec;
+                       tm->tm_min = -tm->tm_min;
+                       tm->tm_hour = -tm->tm_hour;
+                       tm->tm_mday = -tm->tm_mday;
+                       tm->tm_mon = -tm->tm_mon;
+                       tm->tm_year = -tm->tm_year;
+               }
+
+               if (tm->tm_sec < 0)
+               {
+                       tm->tm_sec += 60;
+                       tm->tm_min--;
+               }
+
+               if (tm->tm_min < 0)
+               {
+                       tm->tm_min += 60;
+                       tm->tm_hour--;
+               }
+
+               if (tm->tm_hour < 0)
+               {
+                       tm->tm_hour += 24;
+                       tm->tm_mday--;
+               }
+
+               if (tm->tm_mday < 0)
+               {
+                       if (dt1 < dt2)
+                       {
+                               tm->tm_mday += day_tab[isleap(tm1->tm_year)][tm1->tm_mon - 1];
+                               tm->tm_mon--;
+                       }
+                       else
+                       {
+                               tm->tm_mday += day_tab[isleap(tm2->tm_year)][tm2->tm_mon - 1];
+                               tm->tm_mon--;
+                       }
+               }
+
+               if (tm->tm_mon < 0)
+               {
+                       tm->tm_mon += 12;
+                       tm->tm_year--;
+               }
+
+               /* recover sign if necessary... */
+               if (dt1 < dt2)
+               {
+                       fsec = -fsec;
+                       tm->tm_sec = -tm->tm_sec;
+                       tm->tm_min = -tm->tm_min;
+                       tm->tm_hour = -tm->tm_hour;
+                       tm->tm_mday = -tm->tm_mday;
+                       tm->tm_mon = -tm->tm_mon;
+                       tm->tm_year = -tm->tm_year;
+               }
+
+               if (tm2interval(tm, fsec, result) != 0)
+                       elog(ERROR, "Unable to decode timestamp");
+
+       }
+       else
+               elog(ERROR, "Unable to decode timestamp");
+
+       return result;
+}      /* timestamp_age() */
+
+
+/*----------------------------------------------------------
+ *     Conversion operators.
+ *---------------------------------------------------------*/
+
+
+/* timestamp_text()
+ * Convert timestamp to text data type.
+ */
+text *
+timestamp_text(Timestamp *timestamp)
+{
+       text       *result;
+       char       *str;
+       int                     len;
+
+       if (!PointerIsValid(timestamp))
+               return NULL;
+
+       str = timestamp_out(timestamp);
+
+       if (!PointerIsValid(str))
+               return NULL;
+
+       len = (strlen(str) + VARHDRSZ);
+
+       result = palloc(len);
+
+       VARSIZE(result) = len;
+       memmove(VARDATA(result), str, (len - VARHDRSZ));
+
+       pfree(str);
+
+       return result;
+}      /* timestamp_text() */
+
+
+/* text_timestamp()
+ * Convert text string to timestamp.
+ * Text type is not null terminated, so use temporary string
+ *     then call the standard input routine.
+ */
+Timestamp   *
+text_timestamp(text *str)
+{
+       Timestamp   *result;
+       int                     i;
+       char       *sp,
+                          *dp,
+                               dstr[MAXDATELEN + 1];
+
+       if (!PointerIsValid(str))
+               return NULL;
+
+       sp = VARDATA(str);
+       dp = dstr;
+       for (i = 0; i < (VARSIZE(str) - VARHDRSZ); i++)
+               *dp++ = *sp++;
+       *dp = '\0';
+
+       result = timestamp_in(dstr);
+
+       return result;
+}      /* text_timestamp() */
+
+
+/* interval_text()
+ * Convert interval to text data type.
+ */
+text *
+interval_text(Interval *interval)
+{
+       text       *result;
+       char       *str;
+       int                     len;
+
+       if (!PointerIsValid(interval))
+               return NULL;
+
+       str = interval_out(interval);
+
+       if (!PointerIsValid(str))
+               return NULL;
+
+       len = (strlen(str) + VARHDRSZ);
+
+       result = palloc(len);
+
+       VARSIZE(result) = len;
+       memmove(VARDATA(result), str, (len - VARHDRSZ));
+
+       pfree(str);
+
+       return result;
+}      /* interval_text() */
+
+
+/* text_interval()
+ * Convert text string to interval.
+ * Text type may not be null terminated, so copy to temporary string
+ *     then call the standard input routine.
+ */
+Interval   *
+text_interval(text *str)
+{
+       Interval   *result;
+       int                     i;
+       char       *sp,
+                          *dp,
+                               dstr[MAXDATELEN + 1];
+
+       if (!PointerIsValid(str))
+               return NULL;
+
+       sp = VARDATA(str);
+       dp = dstr;
+       for (i = 0; i < (VARSIZE(str) - VARHDRSZ); i++)
+               *dp++ = *sp++;
+       *dp = '\0';
+
+       result = interval_in(dstr);
+
+       return result;
+}      /* text_interval() */
+
+/* timestamp_trunc()
+ * Extract specified field from timestamp.
+ */
+Timestamp   *
+timestamp_trunc(text *units, Timestamp *timestamp)
+{
+       Timestamp   *result;
+
+       Timestamp       dt;
+       int                     tz;
+       int                     type,
+                               val;
+       int                     i;
+       char       *up,
+                          *lp,
+                               lowunits[MAXDATELEN + 1];
+       double          fsec;
+       char       *tzn;
+       struct tm       tt,
+                          *tm = &tt;
+
+       if ((!PointerIsValid(units)) || (!PointerIsValid(timestamp)))
+               return NULL;
+
+       result = palloc(sizeof(Timestamp));
+
+       up = VARDATA(units);
+       lp = lowunits;
+       for (i = 0; i < (VARSIZE(units) - VARHDRSZ); i++)
+               *lp++ = tolower(*up++);
+       *lp = '\0';
+
+       type = DecodeUnits(0, lowunits, &val);
+
+       if (TIMESTAMP_NOT_FINITE(*timestamp))
+       {
+#if NOT_USED
+/* should return null but Postgres doesn't like that currently. - tgl 97/06/12 */
+               elog(ERROR, "Timestamp is not finite", NULL);
+#endif
+               *result = 0;
+
+       }
+       else
+       {
+               dt = (TIMESTAMP_IS_RELATIVE(*timestamp) ? SetTimestamp(*timestamp) : *timestamp);
+
+               if ((type == UNITS) && (timestamp2tm(dt, &tz, tm, &fsec, &tzn) == 0))
+               {
+                       switch (val)
+                       {
+                               case DTK_MILLENIUM:
+                                       tm->tm_year = (tm->tm_year / 1000) * 1000;
+                               case DTK_CENTURY:
+                                       tm->tm_year = (tm->tm_year / 100) * 100;
+                               case DTK_DECADE:
+                                       tm->tm_year = (tm->tm_year / 10) * 10;
+                               case DTK_YEAR:
+                                       tm->tm_mon = 1;
+                               case DTK_QUARTER:
+                                       tm->tm_mon = (3 * (tm->tm_mon / 4)) + 1;
+                               case DTK_MONTH:
+                                       tm->tm_mday = 1;
+                               case DTK_DAY:
+                                       tm->tm_hour = 0;
+                               case DTK_HOUR:
+                                       tm->tm_min = 0;
+                               case DTK_MINUTE:
+                                       tm->tm_sec = 0;
+                               case DTK_SECOND:
+                                       fsec = 0;
+                                       break;
+
+                               case DTK_MILLISEC:
+                                       fsec = rint(fsec * 1000) / 1000;
+                                       break;
+
+                               case DTK_MICROSEC:
+                                       fsec = rint(fsec * 1000000) / 1000000;
+                                       break;
+
+                               default:
+                                       elog(ERROR, "Timestamp units '%s' not supported", lowunits);
+                                       result = NULL;
+                       }
+
+                       if (IS_VALID_UTIME(tm->tm_year, tm->tm_mon, tm->tm_mday))
+                       {
+#ifdef USE_POSIX_TIME
+                               tm->tm_isdst = -1;
+                               tm->tm_year -= 1900;
+                               tm->tm_mon -= 1;
+                               tm->tm_isdst = -1;
+                               mktime(tm);
+                               tm->tm_year += 1900;
+                               tm->tm_mon += 1;
+
+#if defined(HAVE_TM_ZONE)
+                               tz = -(tm->tm_gmtoff);  /* tm_gmtoff is Sun/DEC-ism */
+#elif defined(HAVE_INT_TIMEZONE)
+
+#ifdef __CYGWIN__
+                               tz = (tm->tm_isdst ? (_timezone - 3600) : _timezone);
+#else
+                               tz = (tm->tm_isdst ? (timezone - 3600) : timezone);
+#endif
+
+#else
+#error USE_POSIX_TIME is defined but neither HAVE_TM_ZONE or HAVE_INT_TIMEZONE are defined
+#endif
+
+#else                                                  /* !USE_POSIX_TIME */
+                               tz = CTimeZone;
+#endif
+                       }
+                       else
+                       {
+                               tm->tm_isdst = 0;
+                               tz = 0;
+                       }
+
+                       if (tm2timestamp(tm, fsec, &tz, result) != 0)
+                               elog(ERROR, "Unable to truncate timestamp to '%s'", lowunits);
+
+#if NOT_USED
+               }
+               else if ((type == RESERV) && (val == DTK_EPOCH))
+               {
+                       TIMESTAMP_EPOCH(*result);
+                       *result = dt - SetTimestamp(*result);
+#endif
+
+               }
+               else
+               {
+                       elog(ERROR, "Timestamp units '%s' not recognized", lowunits);
+                       result = NULL;
+               }
+       }
+
+       return result;
+}      /* timestamp_trunc() */
+
+/* interval_trunc()
+ * Extract specified field from interval.
+ */
+Interval   *
+interval_trunc(text *units, Interval *interval)
+{
+       Interval   *result;
+
+       int                     type,
+                               val;
+       int                     i;
+       char       *up,
+                          *lp,
+                               lowunits[MAXDATELEN + 1];
+       double          fsec;
+       struct tm       tt,
+                          *tm = &tt;
+
+       if ((!PointerIsValid(units)) || (!PointerIsValid(interval)))
+               return NULL;
+
+       result = palloc(sizeof(Interval));
+
+       up = VARDATA(units);
+       lp = lowunits;
+       for (i = 0; i < (VARSIZE(units) - VARHDRSZ); i++)
+               *lp++ = tolower(*up++);
+       *lp = '\0';
+
+       type = DecodeUnits(0, lowunits, &val);
+
+       if (INTERVAL_IS_INVALID(*interval))
+       {
+#if NOT_USED
+               elog(ERROR, "Interval is not finite", NULL);
+#endif
+               result = NULL;
+
+       }
+       else if (type == UNITS)
+       {
+
+               if (interval2tm(*interval, tm, &fsec) == 0)
+               {
+                       switch (val)
+                       {
+                               case DTK_MILLENIUM:
+                                       tm->tm_year = (tm->tm_year / 1000) * 1000;
+                               case DTK_CENTURY:
+                                       tm->tm_year = (tm->tm_year / 100) * 100;
+                               case DTK_DECADE:
+                                       tm->tm_year = (tm->tm_year / 10) * 10;
+                               case DTK_YEAR:
+                                       tm->tm_mon = 0;
+                               case DTK_QUARTER:
+                                       tm->tm_mon = (3 * (tm->tm_mon / 4));
+                               case DTK_MONTH:
+                                       tm->tm_mday = 0;
+                               case DTK_DAY:
+                                       tm->tm_hour = 0;
+                               case DTK_HOUR:
+                                       tm->tm_min = 0;
+                               case DTK_MINUTE:
+                                       tm->tm_sec = 0;
+                               case DTK_SECOND:
+                                       fsec = 0;
+                                       break;
+
+                               case DTK_MILLISEC:
+                                       fsec = rint(fsec * 1000) / 1000;
+                                       break;
+
+                               case DTK_MICROSEC:
+                                       fsec = rint(fsec * 1000000) / 1000000;
+                                       break;
+
+                               default:
+                                       elog(ERROR, "Interval units '%s' not supported", lowunits);
+                                       result = NULL;
+                       }
+
+                       if (tm2interval(tm, fsec, result) != 0)
+                               elog(ERROR, "Unable to truncate interval to '%s'", lowunits);
+
+               }
+               else
+               {
+                       elog(NOTICE, "Interval out of range");
+                       result = NULL;
+               }
+
+#if NOT_USED
+       }
+       else if ((type == RESERV) && (val == DTK_EPOCH))
+       {
+               *result = interval->time;
+               if (interval->month != 0)
+               {
+                       *result += ((365.25 * 86400) * (interval->month / 12));
+                       *result += ((30 * 86400) * (interval->month % 12));
+               }
+#endif
+
+       }
+       else
+       {
+               elog(ERROR, "Interval units '%s' not recognized", textout(units));
+               result = NULL;
+       }
+
+       return result;
+}      /* interval_trunc() */
+
+
+/* timestamp_part()
+ * Extract specified field from timestamp.
+ */
+float64
+timestamp_part(text *units, Timestamp *timestamp)
+{
+       float64         result;
+
+       Timestamp       dt;
+       int                     tz;
+       int                     type,
+                               val;
+       int                     i;
+       char       *up,
+                          *lp,
+                               lowunits[MAXDATELEN + 1];
+       double          dummy;
+       double          fsec;
+       char       *tzn;
+       struct tm       tt,
+                          *tm = &tt;
+
+       if ((!PointerIsValid(units)) || (!PointerIsValid(timestamp)))
+               return NULL;
+
+       result = palloc(sizeof(float64data));
+
+       up = VARDATA(units);
+       lp = lowunits;
+       for (i = 0; i < (VARSIZE(units) - VARHDRSZ); i++)
+               *lp++ = tolower(*up++);
+       *lp = '\0';
+
+       type = DecodeUnits(0, lowunits, &val);
+       if (type == IGNORE)
+               type = DecodeSpecial(0, lowunits, &val);
+
+       if (TIMESTAMP_NOT_FINITE(*timestamp))
+       {
+#if NOT_USED
+/* should return null but Postgres doesn't like that currently. - tgl 97/06/12 */
+               elog(ERROR, "Timestamp is not finite", NULL);
+#endif
+               *result = 0;
+
+       }
+       else
+       {
+               dt = (TIMESTAMP_IS_RELATIVE(*timestamp) ? SetTimestamp(*timestamp) : *timestamp);
+
+               if ((type == UNITS) && (timestamp2tm(dt, &tz, tm, &fsec, &tzn) == 0))
+               {
+                       switch (val)
+                       {
+                               case DTK_TZ:
+                                       *result = tz;
+                                       break;
+
+                               case DTK_TZ_MINUTE:
+                                       *result = tz / 60;
+                                       TMODULO(*result, dummy, 60e0);
+                                       break;
+
+                               case DTK_TZ_HOUR:
+                                       dummy = tz;
+                                       TMODULO(dummy, *result, 3600e0);
+                                       break;
+
+                               case DTK_MICROSEC:
+                                       *result = (fsec * 1000000);
+                                       break;
+
+                               case DTK_MILLISEC:
+                                       *result = (fsec * 1000);
+                                       break;
+
+                               case DTK_SECOND:
+                                       *result = (tm->tm_sec + fsec);
+                                       break;
+
+                               case DTK_MINUTE:
+                                       *result = tm->tm_min;
+                                       break;
+
+                               case DTK_HOUR:
+                                       *result = tm->tm_hour;
+                                       break;
+
+                               case DTK_DAY:
+                                       *result = tm->tm_mday;
+                                       break;
+
+                               case DTK_MONTH:
+                                       *result = tm->tm_mon;
+                                       break;
+
+                               case DTK_QUARTER:
+                                       *result = (tm->tm_mon / 4) + 1;
+                                       break;
+
+                               case DTK_YEAR:
+                                       *result = tm->tm_year;
+                                       break;
+
+                               case DTK_DECADE:
+                                       *result = (tm->tm_year / 10);
+                                       break;
+
+                               case DTK_CENTURY:
+                                       *result = (tm->tm_year / 100);
+                                       break;
+
+                               case DTK_MILLENIUM:
+                                       *result = (tm->tm_year / 1000);
+                                       break;
+
+                               default:
+                                       elog(ERROR, "Timestamp units '%s' not supported", lowunits);
+                                       *result = 0;
+                       }
+
+               }
+               else if (type == RESERV)
+               {
+                       switch (val)
+                       {
+                               case DTK_EPOCH:
+                                       TIMESTAMP_EPOCH(*result);
+                                       *result = dt - SetTimestamp(*result);
+                                       break;
+
+                               case DTK_DOW:
+                                       if (timestamp2tm(dt, &tz, tm, &fsec, &tzn) != 0)
+                                               elog(ERROR, "Unable to encode timestamp");
+
+                                       *result = j2day(date2j(tm->tm_year, tm->tm_mon, tm->tm_mday));
+                                       break;
+
+                               case DTK_DOY:
+                                       if (timestamp2tm(dt, &tz, tm, &fsec, &tzn) != 0)
+                                               elog(ERROR, "Unable to encode timestamp");
+
+                                       *result = (date2j(tm->tm_year, tm->tm_mon, tm->tm_mday)
+                                                          - date2j(tm->tm_year, 1, 1) + 1);
+                                       break;
+
+                               default:
+                                       elog(ERROR, "Timestamp units '%s' not supported", lowunits);
+                                       *result = 0;
+                       }
+
+               }
+               else
+               {
+                       elog(ERROR, "Timestamp units '%s' not recognized", lowunits);
+                       *result = 0;
+               }
+       }
+
+       return result;
+}      /* timestamp_part() */
+
+
+/* interval_part()
+ * Extract specified field from interval.
+ */
+float64
+interval_part(text *units, Interval *interval)
+{
+       float64         result;
+
+       int                     type,
+                               val;
+       int                     i;
+       char       *up,
+                          *lp,
+                               lowunits[MAXDATELEN + 1];
+       double          fsec;
+       struct tm       tt,
+                          *tm = &tt;
+
+       if ((!PointerIsValid(units)) || (!PointerIsValid(interval)))
+               return NULL;
+
+       result = palloc(sizeof(float64data));
+
+       up = VARDATA(units);
+       lp = lowunits;
+       for (i = 0; i < (VARSIZE(units) - VARHDRSZ); i++)
+               *lp++ = tolower(*up++);
+       *lp = '\0';
+
+       type = DecodeUnits(0, lowunits, &val);
+       if (type == IGNORE)
+               type = DecodeSpecial(0, lowunits, &val);
+
+       if (INTERVAL_IS_INVALID(*interval))
+       {
+#if NOT_USED
+               elog(ERROR, "Interval is not finite");
+#endif
+               *result = 0;
+
+       }
+       else if (type == UNITS)
+       {
+
+               if (interval2tm(*interval, tm, &fsec) == 0)
+               {
+                       switch (val)
+                       {
+                               case DTK_MICROSEC:
+                                       *result = (fsec * 1000000);
+                                       break;
+
+                               case DTK_MILLISEC:
+                                       *result = (fsec * 1000);
+                                       break;
+
+                               case DTK_SECOND:
+                                       *result = (tm->tm_sec + fsec);
+                                       break;
+
+                               case DTK_MINUTE:
+                                       *result = tm->tm_min;
+                                       break;
+
+                               case DTK_HOUR:
+                                       *result = tm->tm_hour;
+                                       break;
+
+                               case DTK_DAY:
+                                       *result = tm->tm_mday;
+                                       break;
+
+                               case DTK_MONTH:
+                                       *result = tm->tm_mon;
+                                       break;
+
+                               case DTK_QUARTER:
+                                       *result = (tm->tm_mon / 4) + 1;
+                                       break;
+
+                               case DTK_YEAR:
+                                       *result = tm->tm_year;
+                                       break;
+
+                               case DTK_DECADE:
+                                       *result = (tm->tm_year / 10);
+                                       break;
+
+                               case DTK_CENTURY:
+                                       *result = (tm->tm_year / 100);
+                                       break;
+
+                               case DTK_MILLENIUM:
+                                       *result = (tm->tm_year / 1000);
+                                       break;
+
+                               default:
+                                       elog(ERROR, "Interval units '%s' not yet supported", textout(units));
+                                       result = NULL;
+                       }
+
+               }
+               else
+               {
+                       elog(NOTICE, "Interval out of range");
+                       *result = 0;
+               }
+
+       }
+       else if ((type == RESERV) && (val == DTK_EPOCH))
+       {
+               *result = interval->time;
+               if (interval->month != 0)
+               {
+                       *result += ((365.25 * 86400) * (interval->month / 12));
+                       *result += ((30 * 86400) * (interval->month % 12));
+               }
+
+       }
+       else
+       {
+               elog(ERROR, "Interval units '%s' not recognized", textout(units));
+               *result = 0;
+       }
+
+       return result;
+}      /* interval_part() */
+
+
+/* timestamp_zone()
+ * Encode timestamp type with specified time zone.
+ */
+text *
+timestamp_zone(text *zone, Timestamp *timestamp)
+{
+       text       *result;
+
+       Timestamp       dt;
+       int                     tz;
+       int                     type,
+                               val;
+       int                     i;
+       char       *up,
+                          *lp,
+                               lowzone[MAXDATELEN + 1];
+       char       *tzn,
+                               upzone[MAXDATELEN + 1];
+       double          fsec;
+       struct tm       tt,
+                          *tm = &tt;
+       char            buf[MAXDATELEN + 1];
+       int                     len;
+
+       if ((!PointerIsValid(zone)) || (!PointerIsValid(timestamp)))
+               return NULL;
+
+       up = VARDATA(zone);
+       lp = lowzone;
+       for (i = 0; i < (VARSIZE(zone) - VARHDRSZ); i++)
+               *lp++ = tolower(*up++);
+       *lp = '\0';
+
+       type = DecodeSpecial(0, lowzone, &val);
+
+       if (TIMESTAMP_NOT_FINITE(*timestamp))
+       {
+
+               /*
+                * could return null but Postgres doesn't like that currently. -
+                * tgl 97/06/12
+                */
+               elog(ERROR, "Timestamp is not finite");
+               result = NULL;
+
+       }
+       else if ((type == TZ) || (type == DTZ))
+       {
+               tm->tm_isdst = ((type == DTZ) ? 1 : 0);
+               tz = val * 60;
+
+               dt = (TIMESTAMP_IS_RELATIVE(*timestamp) ? SetTimestamp(*timestamp) : *timestamp);
+               dt = dt2local(dt, tz);
+
+               if (timestamp2tm(dt, NULL, tm, &fsec, NULL) != 0)
+                       elog(ERROR, "Timestamp not legal");
+
+               up = upzone;
+               lp = lowzone;
+               for (i = 0; *lp != '\0'; i++)
+                       *up++ = toupper(*lp++);
+               *up = '\0';
+
+               tzn = upzone;
+               EncodeDateTime(tm, fsec, &tz, &tzn, DateStyle, buf);
+
+               len = (strlen(buf) + VARHDRSZ);
+
+               result = palloc(len);
+
+               VARSIZE(result) = len;
+               memmove(VARDATA(result), buf, (len - VARHDRSZ));
+
+       }
+       else
+       {
+               elog(ERROR, "Time zone '%s' not recognized", lowzone);
+               result = NULL;
+       }
+
+       return result;
+}      /* timestamp_zone() */
index bf93830ca21ccd3ca45352e8815fa2f7fd7a2640..482b299c55d6c4843e1620775b21b5b39fda1a80 100644 (file)
@@ -37,7 +37,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: catversion.h,v 1.14 2000/02/15 20:49:23 tgl Exp $
+ * $Id: catversion.h,v 1.15 2000/02/16 17:26:06 thomas Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -53,6 +53,6 @@
  */
 
 /*                          yyyymmddN */
-#define CATALOG_VERSION_NO  200002151
+#define CATALOG_VERSION_NO  200002161
 
 #endif
index 7376e3ee72deade8d83fad7bf36bd3ea9787a184..67c761e3690be43b6f7fd86c85a6a5056635176c 100644 (file)
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_aggregate.h,v 1.22 2000/01/26 05:57:56 momjian Exp $
+ * $Id: pg_aggregate.h,v 1.23 2000/02/16 17:26:06 thomas Exp $
  *
  * NOTES
  *       the genbki.sh script reads this file and generates .bki
@@ -95,7 +95,7 @@ DATA(insert OID = 0 ( avg     PGUID int2pl      int2inc       int2div                 21       21   21   21 _nul
 DATA(insert OID = 0 ( avg      PGUID float4pl    float4inc float4div      700  700  700  700 _null_ 0.0 ));
 DATA(insert OID = 0 ( avg      PGUID float8pl    float8inc float8div      701  701  701  701 _null_ 0.0 ));
 DATA(insert OID = 0 ( avg      PGUID cash_pl     float8inc cash_div_flt8  790  790  701  790 _null_ 0.0 ));
-DATA(insert OID = 0 ( avg      PGUID timespan_pl float8inc timespan_div  1186 1186  701 1186 _null_ 0.0 ));
+DATA(insert OID = 0 ( avg      PGUID interval_pl float8inc interval_div  1186 1186  701 1186 _null_ 0.0 ));
 DATA(insert OID = 0 ( avg      PGUID numeric_add numeric_inc numeric_div 1700 1700 1700 1700 _null_ 0 ));
 
 DATA(insert OID = 0 ( sum      PGUID int8pl                    - -   20   20 0   20 _null_ _null_ ));
@@ -104,7 +104,7 @@ DATA(insert OID = 0 ( sum   PGUID int2pl                    - -   21   21 0   21 _null_ _null_ ));
 DATA(insert OID = 0 ( sum      PGUID float4pl                  - -  700  700 0  700 _null_ _null_ ));
 DATA(insert OID = 0 ( sum      PGUID float8pl                  - -  701  701 0  701 _null_ _null_ ));
 DATA(insert OID = 0 ( sum      PGUID cash_pl                   - -  790  790 0  790 _null_ _null_ ));
-DATA(insert OID = 0 ( sum      PGUID timespan_pl               - - 1186 1186 0 1186 _null_ _null_ ));
+DATA(insert OID = 0 ( sum      PGUID interval_pl               - - 1186 1186 0 1186 _null_ _null_ ));
 DATA(insert OID = 0 ( sum      PGUID numeric_add               - - 1700 1700 0 1700 _null_ _null_ ));
 
 DATA(insert OID = 0 ( max      PGUID int8larger                - -   20   20 0   20 _null_ _null_ ));
@@ -115,8 +115,8 @@ DATA(insert OID = 0 ( max   PGUID float8larger              - -  701  701 0  701 _null_ _null_
 DATA(insert OID = 0 ( max      PGUID int4larger                - -  702  702 0  702 _null_ _null_ ));
 DATA(insert OID = 0 ( max      PGUID date_larger               - - 1082 1082 0 1082 _null_ _null_ ));
 DATA(insert OID = 0 ( max      PGUID cashlarger                - -  790  790 0  790 _null_ _null_ ));
-DATA(insert OID = 0 ( max      PGUID datetime_larger   - - 1184 1184 0 1184 _null_ _null_ ));
-DATA(insert OID = 0 ( max      PGUID timespan_larger   - - 1186 1186 0 1186 _null_ _null_ ));
+DATA(insert OID = 0 ( max      PGUID timestamp_larger  - - 1184 1184 0 1184 _null_ _null_ ));
+DATA(insert OID = 0 ( max      PGUID interval_larger   - - 1186 1186 0 1186 _null_ _null_ ));
 DATA(insert OID = 0 ( max      PGUID text_larger               - -   25   25 0   25 _null_ _null_ ));
 DATA(insert OID = 0 ( max      PGUID numeric_larger    - - 1700 1700 0 1700 _null_ _null_ ));
 
@@ -128,8 +128,8 @@ DATA(insert OID = 0 ( min   PGUID float8smaller             - -  701  701 0  701 _null_ _null
 DATA(insert OID = 0 ( min      PGUID int4smaller               - -  702  702 0  702 _null_ _null_ ));
 DATA(insert OID = 0 ( min      PGUID date_smaller              - - 1082 1082 0 1082 _null_ _null_ ));
 DATA(insert OID = 0 ( min      PGUID cashsmaller               - -  790  790 0  790 _null_ _null_ ));
-DATA(insert OID = 0 ( min      PGUID datetime_smaller  - - 1184 1184 0 1184 _null_ _null_ ));
-DATA(insert OID = 0 ( min      PGUID timespan_smaller  - - 1186 1186 0 1186 _null_ _null_ ));
+DATA(insert OID = 0 ( min      PGUID timestamp_smaller - - 1184 1184 0 1184 _null_ _null_ ));
+DATA(insert OID = 0 ( min      PGUID interval_smaller  - - 1186 1186 0 1186 _null_ _null_ ));
 DATA(insert OID = 0 ( min      PGUID text_smaller              - -   25   25 0   25 _null_ _null_ ));
 DATA(insert OID = 0 ( min      PGUID numeric_smaller   - - 1700 1700 0 1700 _null_ _null_ ));
 
index f33c6894afc9f07d7dfbb0d3ba8f2f5f2851d185..c036ef5eac1b7c509b060afe0170fd5287e831cf 100644 (file)
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_opclass.h,v 1.28 2000/02/10 19:51:45 momjian Exp $
+ * $Id: pg_opclass.h,v 1.29 2000/02/16 17:26:07 thomas Exp $
  *
  * NOTES
  *       the genbki.sh script reads this file and generates .bki
@@ -106,9 +106,9 @@ DATA(insert OID = 1115 (    time_ops           1083   ));
 DESCR("");
 DATA(insert OID = 1181 (       name_ops                 19   ));
 DESCR("");
-DATA(insert OID = 1312 (       datetime_ops   1184   ));
+DATA(insert OID = 1312 (       timestamp_ops  1184   ));
 DESCR("");
-DATA(insert OID = 1313 (       timespan_ops   1186   ));
+DATA(insert OID = 1313 (       interval_ops   1186   ));
 DESCR("");
 DATA(insert OID = 810  (       macaddr_ops     829       ));
 DESCR("");
index fd33b4b510fab95b1d166cb2b578364e3c834695..e510c621d02e2a649a32809b68294c00708d937e 100644 (file)
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_operator.h,v 1.67 2000/02/10 19:51:45 momjian Exp $
+ * $Id: pg_operator.h,v 1.68 2000/02/16 17:26:07 thomas Exp $
  *
  * NOTES
  *       the genbki.sh script reads this file and generates .bki
@@ -244,18 +244,18 @@ DATA(insert OID = 568 (  "<"         PGUID 0 b t f 703 703  16 569 571 0 0 reltimelt
 DATA(insert OID = 569 (  ">"      PGUID 0 b t f 703 703  16 568 570 0 0 reltimegt scalargtsel scalargtjoinsel ));
 DATA(insert OID = 570 (  "<="     PGUID 0 b t f 703 703  16 571 569 0 0 reltimele scalarltsel scalarltjoinsel ));
 DATA(insert OID = 571 (  ">="     PGUID 0 b t f 703 703  16 570 568 0 0 reltimege scalargtsel scalargtjoinsel ));
-DATA(insert OID = 572 (  "~="     PGUID 0 b t f 704 704  16 572   0   0   0 intervalsame eqsel eqjoinsel ));
-DATA(insert OID = 573 (  "<<"     PGUID 0 b t f 704 704  16   0   0   0   0 intervalct - - ));
-DATA(insert OID = 574 (  "&&"     PGUID 0 b t f 704 704  16   0   0   0   0 intervalov - - ));
-DATA(insert OID = 575 (  "#="     PGUID 0 b t f 704 703  16   0 576   0   0 intervalleneq - - ));
-DATA(insert OID = 576 (  "#<>"    PGUID 0 b t f 704 703  16   0 575   0   0 intervallenne - - ));
-DATA(insert OID = 577 (  "#<"     PGUID 0 b t f 704 703  16   0 580   0   0 intervallenlt - - ));
-DATA(insert OID = 578 (  "#>"     PGUID 0 b t f 704 703  16   0 579   0   0 intervallengt - - ));
-DATA(insert OID = 579 (  "#<="    PGUID 0 b t f 704 703  16   0 578   0   0 intervallenle - - ));
-DATA(insert OID = 580 (  "#>="    PGUID 0 b t f 704 703  16   0 577   0   0 intervallenge - - ));
+DATA(insert OID = 572 (  "~="     PGUID 0 b t f 704 704  16 572   0   0   0 tintervalsame eqsel eqjoinsel ));
+DATA(insert OID = 573 (  "<<"     PGUID 0 b t f 704 704  16   0   0   0   0 tintervalct - - ));
+DATA(insert OID = 574 (  "&&"     PGUID 0 b t f 704 704  16   0   0   0   0 tintervalov - - ));
+DATA(insert OID = 575 (  "#="     PGUID 0 b t f 704 703  16   0 576   0   0 tintervalleneq - - ));
+DATA(insert OID = 576 (  "#<>"    PGUID 0 b t f 704 703  16   0 575   0   0 tintervallenne - - ));
+DATA(insert OID = 577 (  "#<"     PGUID 0 b t f 704 703  16   0 580   0   0 tintervallenlt - - ));
+DATA(insert OID = 578 (  "#>"     PGUID 0 b t f 704 703  16   0 579   0   0 tintervallengt - - ));
+DATA(insert OID = 579 (  "#<="    PGUID 0 b t f 704 703  16   0 578   0   0 tintervallenle - - ));
+DATA(insert OID = 580 (  "#>="    PGUID 0 b t f 704 703  16   0 577   0   0 tintervallenge - - ));
 DATA(insert OID = 581 (  "+"      PGUID 0 b t f 702 703 702   0   0 0 0 timepl - - ));
 DATA(insert OID = 582 (  "-"      PGUID 0 b t f 702 703 702   0   0 0 0 timemi - - ));
-DATA(insert OID = 583 (  "<?>"    PGUID 0 b t f 702 704  16   0   0   0   0 ininterval - - ));
+DATA(insert OID = 583 (  "<?>"    PGUID 0 b t f 702 704  16   0   0   0   0 intinterval - - ));
 DATA(insert OID = 584 (  "-"      PGUID 0 l t f   0 700 700   0   0   0   0 float4um - - ));
 DATA(insert OID = 585 (  "-"      PGUID 0 l t f   0 701 701   0   0   0   0 float8um - - ));
 DATA(insert OID = 586 (  "+"      PGUID 0 b t f 700 700 700 586   0   0   0 float4pl - - ));
@@ -274,7 +274,7 @@ DATA(insert OID = 598 (  "%"           PGUID 0 l t f   0 701 701   0   0   0   0 dtrunc
 DATA(insert OID = 599 (  "%"      PGUID 0 r t f 701   0 701   0   0   0   0 dround - - ));
 DATA(insert OID = 1282 (  ":"          PGUID 0 l t f   0 701 701       0       0       0       0 dexp - - ));
 DATA(insert OID = 1283 (  ";"          PGUID 0 l t f   0 701 701       0       0       0       0 dlog1 - - ));
-DATA(insert OID = 1284 (  "|"          PGUID 0 l t f   0 704 702       0       0       0       0 intervalstart - - ));
+DATA(insert OID = 1284 (  "|"          PGUID 0 l t f   0 704 702       0       0       0       0 tintervalstart - - ));
 DATA(insert OID = 606 (  "<#>"         PGUID 0 b t f 702 702 704       0       0       0       0 mktinterval - - ));
 DATA(insert OID = 607 (  "="      PGUID 0 b t t  26  26  16 607 608 609 609 oideq eqsel eqjoinsel ));
 #define MIN_OIDCMP 607 /* used by cache code */
@@ -399,12 +399,12 @@ DATA(insert OID =  807 (  "/"        PGUID 0 b t f  603  600      603    0  0 0 0 box_div
 DATA(insert OID =  808 (  "?-"    PGUID 0 b t f  600  600       16  808  0 0 0 point_horiz - - ));
 DATA(insert OID =  809 (  "?|"    PGUID 0 b t f  600  600       16  809  0 0 0 point_vert - - ));
 
-DATA(insert OID = 811 (  "="      PGUID 0 b t f 704 704  16 811 812   0   0 intervaleq eqsel eqjoinsel ));
-DATA(insert OID = 812 (  "<>"     PGUID 0 b t f 704 704  16 812 811   0   0 intervalne neqsel neqjoinsel ));
-DATA(insert OID = 813 (  "<"      PGUID 0 b t f 704 704  16 814 816   0   0 intervallt scalarltsel scalarltjoinsel ));
-DATA(insert OID = 814 (  ">"      PGUID 0 b t f 704 704  16 813 815   0   0 intervalgt scalargtsel scalargtjoinsel ));
-DATA(insert OID = 815 (  "<="     PGUID 0 b t f 704 704  16 816 814   0   0 intervalle scalarltsel scalarltjoinsel ));
-DATA(insert OID = 816 (  ">="     PGUID 0 b t f 704 704  16 815 813   0   0 intervalge scalargtsel scalargtjoinsel ));
+DATA(insert OID = 811 (  "="      PGUID 0 b t f 704 704  16 811 812   0   0 tintervaleq eqsel eqjoinsel ));
+DATA(insert OID = 812 (  "<>"     PGUID 0 b t f 704 704  16 812 811   0   0 tintervalne neqsel neqjoinsel ));
+DATA(insert OID = 813 (  "<"      PGUID 0 b t f 704 704  16 814 816   0   0 tintervallt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 814 (  ">"      PGUID 0 b t f 704 704  16 813 815   0   0 tintervalgt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 815 (  "<="     PGUID 0 b t f 704 704  16 816 814   0   0 tintervalle scalarltsel scalarltjoinsel ));
+DATA(insert OID = 816 (  ">="     PGUID 0 b t f 704 704  16 815 813   0   0 tintervalge scalargtsel scalargtjoinsel ));
 
 DATA(insert OID = 843 (  "*"      PGUID 0 b t f  790  700      790 845   0   0   0 cash_mul_flt4 - - ));
 DATA(insert OID = 844 (  "/"      PGUID 0 b t f  790  700      790   0   0   0   0 cash_div_flt4 - - ));
@@ -536,37 +536,30 @@ DATA(insert OID = 1234 (  "~*"            PGUID 0 b t f  1042  25  16 0 1235      0 0 texticreg
 #define OID_BPCHAR_ICREGEXEQ_OP                1234
 DATA(insert OID = 1235 ( "!~*"         PGUID 0 b t f  1042  25  16 0 1234      0 0 texticregexne neqsel neqjoinsel ));
 
-DATA(insert OID = 1300 (  "="          PGUID 0 b t t  1296 1296 16 1300 1301 1302 1302 timestampeq eqsel eqjoinsel ));
-DATA(insert OID = 1301 (  "<>"         PGUID 0 b t f  1296 1296 16 1301 1300 0 0 timestampne neqsel neqjoinsel ));
-DATA(insert OID = 1302 (  "<"          PGUID 0 b t f  1296 1296 16 1303 1305 0 0 timestamplt scalarltsel scalarltjoinsel ));
-DATA(insert OID = 1303 (  ">"          PGUID 0 b t f  1296 1296 16 1302 1304 0 0 timestampgt scalargtsel scalargtjoinsel ));
-DATA(insert OID = 1304 (  "<="         PGUID 0 b t f  1296 1296 16 1305 1303 0 0 timestample scalarltsel scalarltjoinsel ));
-DATA(insert OID = 1305 (  ">="         PGUID 0 b t f  1296 1296 16 1304 1302 0 0 timestampge scalargtsel scalargtjoinsel ));
-
-/* datetime operators */
+/* timestamp operators */
 /* name, owner, prec, kind, isleft, canhash, left, right, result, com, negate, lsortop, rsortop, oprcode, operrest, oprjoin */
-DATA(insert OID = 1320 (  "="     PGUID 0 b t f 1184 1184       16 1320 1321 1322 1322 datetime_eq eqsel eqjoinsel ));
-DATA(insert OID = 1321 (  "<>"    PGUID 0 b t f 1184 1184       16 1321 1320 0 0 datetime_ne neqsel neqjoinsel ));
-DATA(insert OID = 1322 (  "<"     PGUID 0 b t f 1184 1184       16 1324 1325 0 0 datetime_lt scalarltsel scalarltjoinsel ));
-DATA(insert OID = 1323 (  "<="    PGUID 0 b t f 1184 1184       16 1325 1324 0 0 datetime_le scalarltsel scalarltjoinsel ));
-DATA(insert OID = 1324 (  ">"     PGUID 0 b t f 1184 1184       16 1322 1323 0 0 datetime_gt scalargtsel scalargtjoinsel ));
-DATA(insert OID = 1325 (  ">="    PGUID 0 b t f 1184 1184       16 1323 1322 0 0 datetime_ge scalargtsel scalargtjoinsel ));
-
-DATA(insert OID = 1327 (  "+"     PGUID 0 b t f 1184 1186 1184    0    0 0 0 datetime_pl_span - - ));
-DATA(insert OID = 1328 (  "-"     PGUID 0 b t f 1184 1184 1186    0    0 0 0 datetime_mi - - ));
-DATA(insert OID = 1329 (  "-"     PGUID 0 b t f 1184 1186 1184    0    0 0 0 datetime_mi_span - - ));
-
-/* timespan operators */
-DATA(insert OID = 1330 (  "="     PGUID 0 b t f 1186 1186       16 1330 1331 1332 1332 timespan_eq eqsel eqjoinsel ));
-DATA(insert OID = 1331 (  "<>"    PGUID 0 b t f 1186 1186       16 1331 1330 0 0 timespan_ne neqsel neqjoinsel ));
-DATA(insert OID = 1332 (  "<"     PGUID 0 b t f 1186 1186       16 1334 1335 0 0 timespan_lt scalarltsel scalarltjoinsel ));
-DATA(insert OID = 1333 (  "<="    PGUID 0 b t f 1186 1186       16 1335 1334 0 0 timespan_le scalarltsel scalarltjoinsel ));
-DATA(insert OID = 1334 (  ">"     PGUID 0 b t f 1186 1186       16 1332 1333 0 0 timespan_gt scalargtsel scalargtjoinsel ));
-DATA(insert OID = 1335 (  ">="    PGUID 0 b t f 1186 1186       16 1333 1332 0 0 timespan_ge scalargtsel scalargtjoinsel ));
-
-DATA(insert OID = 1336 (  "-"     PGUID 0 l t f        0 1186 1186    0        0 0 0 timespan_um - - ));
-DATA(insert OID = 1337 (  "+"     PGUID 0 b t f 1186 1186 1186 1337    0 0 0 timespan_pl - - ));
-DATA(insert OID = 1338 (  "-"     PGUID 0 b t f 1186 1186 1186    0    0 0 0 timespan_mi - - ));
+DATA(insert OID = 1320 (  "="     PGUID 0 b t f 1184 1184       16 1320 1321 1322 1322 timestamp_eq eqsel eqjoinsel ));
+DATA(insert OID = 1321 (  "<>"    PGUID 0 b t f 1184 1184       16 1321 1320 0 0 timestamp_ne neqsel neqjoinsel ));
+DATA(insert OID = 1322 (  "<"     PGUID 0 b t f 1184 1184       16 1324 1325 0 0 timestamp_lt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 1323 (  "<="    PGUID 0 b t f 1184 1184       16 1325 1324 0 0 timestamp_le scalarltsel scalarltjoinsel ));
+DATA(insert OID = 1324 (  ">"     PGUID 0 b t f 1184 1184       16 1322 1323 0 0 timestamp_gt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 1325 (  ">="    PGUID 0 b t f 1184 1184       16 1323 1322 0 0 timestamp_ge scalargtsel scalargtjoinsel ));
+
+DATA(insert OID = 1327 (  "+"     PGUID 0 b t f 1184 1186 1184    0    0 0 0 timestamp_pl_span - - ));
+DATA(insert OID = 1328 (  "-"     PGUID 0 b t f 1184 1184 1186    0    0 0 0 timestamp_mi - - ));
+DATA(insert OID = 1329 (  "-"     PGUID 0 b t f 1184 1186 1184    0    0 0 0 timestamp_mi_span - - ));
+
+/* interval operators */
+DATA(insert OID = 1330 (  "="     PGUID 0 b t f 1186 1186       16 1330 1331 1332 1332 interval_eq eqsel eqjoinsel ));
+DATA(insert OID = 1331 (  "<>"    PGUID 0 b t f 1186 1186       16 1331 1330 0 0 interval_ne neqsel neqjoinsel ));
+DATA(insert OID = 1332 (  "<"     PGUID 0 b t f 1186 1186       16 1334 1335 0 0 interval_lt scalarltsel scalarltjoinsel ));
+DATA(insert OID = 1333 (  "<="    PGUID 0 b t f 1186 1186       16 1335 1334 0 0 interval_le scalarltsel scalarltjoinsel ));
+DATA(insert OID = 1334 (  ">"     PGUID 0 b t f 1186 1186       16 1332 1333 0 0 interval_gt scalargtsel scalargtjoinsel ));
+DATA(insert OID = 1335 (  ">="    PGUID 0 b t f 1186 1186       16 1333 1332 0 0 interval_ge scalargtsel scalargtjoinsel ));
+
+DATA(insert OID = 1336 (  "-"     PGUID 0 l t f        0 1186 1186    0        0 0 0 interval_um - - ));
+DATA(insert OID = 1337 (  "+"     PGUID 0 b t f 1186 1186 1186 1337    0 0 0 interval_pl - - ));
+DATA(insert OID = 1338 (  "-"     PGUID 0 b t f 1186 1186 1186    0    0 0 0 interval_mi - - ));
 
 /* additional geometric operators - thomas 97/04/18 */
 DATA(insert OID = 1420 (  "@@"   PGUID 0 l t f    0  718  600    0    0        0        0 circle_center - - ));
@@ -626,7 +619,7 @@ DATA(insert OID = 1567 (  "##"        PGUID 0 b t f  601  603  600    0  0 0 0 close_s
 DATA(insert OID = 1568 (  "##"   PGUID 0 b t f  628  603  600    0  0 0 0 close_lb - - ));
 DATA(insert OID = 1577 (  "##"   PGUID 0 b t f  628  601  600    0  0 0 0 close_ls - - ));
 DATA(insert OID = 1578 (  "##"   PGUID 0 b t f  601  601  600    0  0 0 0 close_lseg - - ));
-DATA(insert OID = 1585 (  "/"    PGUID 0 b t f 1186  701 1186    0  0 0 0 timespan_div - - ));
+DATA(insert OID = 1585 (  "/"    PGUID 0 b t f 1186  701 1186    0  0 0 0 interval_div - - ));
 
 DATA(insert OID = 1586 (  "<>"   PGUID 0 b t f  601  601       16 1586 1535 0 0 lseg_ne neqsel neqjoinsel ));
 DATA(insert OID = 1587 (  "<"    PGUID 0 b t f  601  601       16 1589 1590 0 0 lseg_lt - - ));
index 87107b1df367553325787ed1c12876d32a2f74ae..64c015fbff25058a8c2b5f1e37d36d911f666b11 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_proc.h,v 1.121 2000/02/15 20:49:23 tgl Exp $
+ * $Id: pg_proc.h,v 1.122 2000/02/16 17:26:07 thomas Exp $
  *
  * NOTES
  *       The script catalog/genbki.sh reads this file and generates .bki
@@ -517,9 +517,9 @@ DATA(insert OID = 246 (  tintervalin           PGUID 11 f t f 1 f 704 "0" 100 0 0 100
 DESCR("(internal)");
 DATA(insert OID = 247 (  tintervalout     PGUID 11 f t f 1 f 23  "0" 100 0 0 100  tintervalout - ));
 DESCR("(internal)");
-DATA(insert OID = 248 (  ininterval               PGUID 11 f t f 2 f 16 "702 704" 100 0 0 100  ininterval - ));
+DATA(insert OID = 248 (  intinterval      PGUID 11 f t f 2 f 16 "702 704" 100 0 0 100  intinterval - ));
 DESCR("abstime in tinterval");
-DATA(insert OID = 249 (  intervalrel      PGUID 11 f t f 1 f 703 "704" 100 0 0 100  intervalrel - ));
+DATA(insert OID = 249 (  tintervalrel     PGUID 11 f t f 1 f 703 "704" 100 0 0 100  tintervalrel - ));
 DESCR("");
 DATA(insert OID = 250 (  timenow                  PGUID 11 f t f 0 f 702 "0" 100 0 0 100  timenow - ));
 DESCR("Current date and time");
@@ -547,27 +547,27 @@ DATA(insert OID = 261 (  reltimele                   PGUID 11 f t t 2 f 16 "703 703" 100 0 0 1
 DESCR("less-than-or-equal");
 DATA(insert OID = 262 (  reltimege                PGUID 11 f t t 2 f 16 "703 703" 100 0 0 100  reltimege - ));
 DESCR("greater-than-or-equal");
-DATA(insert OID = 263 (  intervalsame     PGUID 11 f t f 2 f 16 "704 704" 100 0 0 100  intervalsame - ));
+DATA(insert OID = 263 (  tintervalsame    PGUID 11 f t f 2 f 16 "704 704" 100 0 0 100  tintervalsame - ));
 DESCR("same as");
-DATA(insert OID = 264 (  intervalct               PGUID 11 f t f 2 f 16 "704 704" 100 0 0 100  intervalct - ));
+DATA(insert OID = 264 (  tintervalct      PGUID 11 f t f 2 f 16 "704 704" 100 0 0 100  tintervalct - ));
 DESCR("less-than");
-DATA(insert OID = 265 (  intervalov               PGUID 11 f t f 2 f 16 "704 704" 100 0 0 100  intervalov - ));
+DATA(insert OID = 265 (  tintervalov      PGUID 11 f t f 2 f 16 "704 704" 100 0 0 100  tintervalov - ));
 DESCR("overlaps");
-DATA(insert OID = 266 (  intervalleneq    PGUID 11 f t f 2 f 16 "704 703" 100 0 0 100  intervalleneq - ));
+DATA(insert OID = 266 (  tintervalleneq           PGUID 11 f t f 2 f 16 "704 703" 100 0 0 100  tintervalleneq - ));
 DESCR("length equal");
-DATA(insert OID = 267 (  intervallenne    PGUID 11 f t f 2 f 16 "704 703" 100 0 0 100  intervallenne - ));
+DATA(insert OID = 267 (  tintervallenne           PGUID 11 f t f 2 f 16 "704 703" 100 0 0 100  tintervallenne - ));
 DESCR("length not equal to");
-DATA(insert OID = 268 (  intervallenlt    PGUID 11 f t f 2 f 16 "704 703" 100 0 0 100  intervallenlt - ));
+DATA(insert OID = 268 (  tintervallenlt           PGUID 11 f t f 2 f 16 "704 703" 100 0 0 100  tintervallenlt - ));
 DESCR("length less-than");
-DATA(insert OID = 269 (  intervallengt    PGUID 11 f t f 2 f 16 "704 703" 100 0 0 100  intervallengt - ));
+DATA(insert OID = 269 (  tintervallengt           PGUID 11 f t f 2 f 16 "704 703" 100 0 0 100  tintervallengt - ));
 DESCR("length greater-than");
-DATA(insert OID = 270 (  intervallenle    PGUID 11 f t f 2 f 16 "704 703" 100 0 0 100  intervallenle - ));
+DATA(insert OID = 270 (  tintervallenle           PGUID 11 f t f 2 f 16 "704 703" 100 0 0 100  tintervallenle - ));
 DESCR("length less-than-or-equal");
-DATA(insert OID = 271 (  intervallenge    PGUID 11 f t f 2 f 16 "704 703" 100 0 0 100  intervallenge - ));
+DATA(insert OID = 271 (  tintervallenge           PGUID 11 f t f 2 f 16 "704 703" 100 0 0 100  tintervallenge - ));
 DESCR("length greater-than-or-equal");
-DATA(insert OID = 272 (  intervalstart    PGUID 11 f t f 1 f 702 "704" 100 0 0 100  intervalstart - ));
+DATA(insert OID = 272 (  tintervalstart           PGUID 11 f t f 1 f 702 "704" 100 0 0 100  tintervalstart - ));
 DESCR("start of interval");
-DATA(insert OID = 273 (  intervalend      PGUID 11 f t f 1 f 702 "704" 100 0 0 100  intervalend - ));
+DATA(insert OID = 273 (  tintervalend     PGUID 11 f t f 1 f 702 "704" 100 0 0 100  tintervalend - ));
 DESCR("");
 DATA(insert OID = 274 (  timeofday                PGUID 11 f t f 0 f 25 "0" 100 0 0 100  timeofday - ));
 DESCR("Current date and time with microseconds");
@@ -920,7 +920,7 @@ DATA(insert OID = 669 (  varchar               PGUID 11 f t t 2 f 1043 "1043 23" 100 0 0 1
 DESCR("truncate varchar()");
 
 DATA(insert OID = 676 (  mktinterval      PGUID 11 f t f 2 f 704 "702 702" 100 0 0 100 mktinterval - ));
-DESCR("convert to interval");
+DESCR("convert to tinterval");
 DATA(insert OID = 619 (  oidvectorne      PGUID 11 f t t 2 f 16 "30 30" 100 0 0 100  oidvectorne - ));
 DESCR("less-than");
 DATA(insert OID = 677 (  oidvectorlt      PGUID 11 f t t 2 f 16 "30 30" 100 0 0 100  oidvectorlt - ));
@@ -1052,17 +1052,17 @@ DESCR("gist(internal)");
 DATA(insert OID = 782 (  gistbuild                PGUID 11 f t f 9 f 23 "0" 100 0 0 100  gistbuild - ));
 DESCR("gist(internal)");
 
-DATA(insert OID = 784 (  intervaleq               PGUID 11 f t f 2 f 16 "704 704" 100 0 0 100  intervaleq - ));
+DATA(insert OID = 784 (  tintervaleq      PGUID 11 f t f 2 f 16 "704 704" 100 0 0 100  tintervaleq - ));
 DESCR("equal");
-DATA(insert OID = 785 (  intervalne               PGUID 11 f t f 2 f 16 "704 704" 100 0 0 100  intervalne - ));
+DATA(insert OID = 785 (  tintervalne      PGUID 11 f t f 2 f 16 "704 704" 100 0 0 100  tintervalne - ));
 DESCR("not equal");
-DATA(insert OID = 786 (  intervallt               PGUID 11 f t f 2 f 16 "704 704" 100 0 0 100  intervallt - ));
+DATA(insert OID = 786 (  tintervallt      PGUID 11 f t f 2 f 16 "704 704" 100 0 0 100  tintervallt - ));
 DESCR("less-than");
-DATA(insert OID = 787 (  intervalgt               PGUID 11 f t f 2 f 16 "704 704" 100 0 0 100  intervalgt - ));
+DATA(insert OID = 787 (  tintervalgt      PGUID 11 f t f 2 f 16 "704 704" 100 0 0 100  tintervalgt - ));
 DESCR("greater-than");
-DATA(insert OID = 788 (  intervalle               PGUID 11 f t f 2 f 16 "704 704" 100 0 0 100  intervalle - ));
+DATA(insert OID = 788 (  tintervalle      PGUID 11 f t f 2 f 16 "704 704" 100 0 0 100  tintervalle - ));
 DESCR("less-than-or-equal");
-DATA(insert OID = 789 (  intervalge               PGUID 11 f t f 2 f 16 "704 704" 100 0 0 100  intervalge - ));
+DATA(insert OID = 789 (  tintervalge      PGUID 11 f t f 2 f 16 "704 704" 100 0 0 100  tintervalge - ));
 DESCR("greater-than-or-equal");
 
 /* OIDS 800 - 899 */
@@ -1397,94 +1397,92 @@ DESCR("multiply");
 DATA(insert OID = 1149 (  circle_div_pt    PGUID 11 f t t 2 f 718 "718 600" 100 0 0 100  circle_div_pt - ));
 DESCR("divide");
 
-DATA(insert OID = 1150 (  datetime_in     PGUID 11 f t f 1 f 1184 "0" 100 0 0 100      datetime_in - ));
+DATA(insert OID = 1150 (  timestamp_in    PGUID 11 f t f 1 f 1184 "0" 100 0 0 100      timestamp_in - ));
 DESCR("(internal)");
-DATA(insert OID = 1151 (  datetime_out    PGUID 11 f t f 1 f   23 "0" 100 0 0 100      datetime_out - ));
+DATA(insert OID = 1151 (  timestamp_out           PGUID 11 f t f 1 f   23 "0" 100 0 0 100      timestamp_out - ));
 DESCR("(internal)");
-DATA(insert OID = 1152 (  datetime_eq     PGUID 11 f t f 2 f   16 "1184 1184" 100 0 0 100      datetime_eq - ));
+DATA(insert OID = 1152 (  timestamp_eq    PGUID 11 f t f 2 f   16 "1184 1184" 100 0 0 100      timestamp_eq - ));
 DESCR("equal");
-DATA(insert OID = 1153 (  datetime_ne     PGUID 11 f t f 2 f   16 "1184 1184" 100 0 0 100      datetime_ne - ));
+DATA(insert OID = 1153 (  timestamp_ne    PGUID 11 f t f 2 f   16 "1184 1184" 100 0 0 100      timestamp_ne - ));
 DESCR("not equal");
-DATA(insert OID = 1154 (  datetime_lt     PGUID 11 f t f 2 f   16 "1184 1184" 100 0 0 100      datetime_lt - ));
+DATA(insert OID = 1154 (  timestamp_lt    PGUID 11 f t f 2 f   16 "1184 1184" 100 0 0 100      timestamp_lt - ));
 DESCR("less-than");
-DATA(insert OID = 1155 (  datetime_le     PGUID 11 f t f 2 f   16 "1184 1184" 100 0 0 100      datetime_le - ));
+DATA(insert OID = 1155 (  timestamp_le    PGUID 11 f t f 2 f   16 "1184 1184" 100 0 0 100      timestamp_le - ));
 DESCR("less-than-or-equal");
-DATA(insert OID = 1156 (  datetime_ge     PGUID 11 f t f 2 f   16 "1184 1184" 100 0 0 100      datetime_ge - ));
+DATA(insert OID = 1156 (  timestamp_ge    PGUID 11 f t f 2 f   16 "1184 1184" 100 0 0 100      timestamp_ge - ));
 DESCR("greater-than-or-equal");
-DATA(insert OID = 1157 (  datetime_gt     PGUID 11 f t f 2 f   16 "1184 1184" 100 0 0 100      datetime_gt - ));
+DATA(insert OID = 1157 (  timestamp_gt    PGUID 11 f t f 2 f   16 "1184 1184" 100 0 0 100      timestamp_gt - ));
 DESCR("greater-than");
-DATA(insert OID = 1158 (  datetime_finite  PGUID 11 f t f 1 f  16 "1184" 100 0 0 100  datetime_finite - ));
+DATA(insert OID = 1158 (  timestamp_finite  PGUID 11 f t f 1 f 16 "1184" 100 0 0 100  timestamp_finite - ));
 DESCR("");
-DATA(insert OID = 1159 (  datetime_zone    PGUID 11 f t f 2 f  25 "25 1184" 100 0 0 100  datetime_zone - ));
+DATA(insert OID = 1159 (  timestamp_zone    PGUID 11 f t f 2 f 25 "25 1184" 100 0 0 100  timestamp_zone - ));
 DESCR("");
 
-DATA(insert OID = 1160 (  timespan_in     PGUID 11 f t f 1 f 1186 "0" 100 0 0 100      timespan_in - ));
+DATA(insert OID = 1160 (  interval_in     PGUID 11 f t f 1 f 1186 "0" 100 0 0 100      interval_in - ));
 DESCR("(internal)");
-DATA(insert OID = 1161 (  timespan_out    PGUID 11 f t f 1 f 23 "0" 100 0 0 100  timespan_out - ));
+DATA(insert OID = 1161 (  interval_out    PGUID 11 f t f 1 f 23 "0" 100 0 0 100  interval_out - ));
 DESCR("(internal)");
-DATA(insert OID = 1162 (  timespan_eq     PGUID 11 f t f 2 f 16 "1186 1186" 100 0 0 100  timespan_eq - ));
+DATA(insert OID = 1162 (  interval_eq     PGUID 11 f t f 2 f 16 "1186 1186" 100 0 0 100  interval_eq - ));
 DESCR("equal");
-DATA(insert OID = 1163 (  timespan_ne     PGUID 11 f t f 2 f 16 "1186 1186" 100 0 0 100  timespan_ne - ));
+DATA(insert OID = 1163 (  interval_ne     PGUID 11 f t f 2 f 16 "1186 1186" 100 0 0 100  interval_ne - ));
 DESCR("not equal");
-DATA(insert OID = 1164 (  timespan_lt     PGUID 11 f t f 2 f 16 "1186 1186" 100 0 0 100  timespan_lt - ));
+DATA(insert OID = 1164 (  interval_lt     PGUID 11 f t f 2 f 16 "1186 1186" 100 0 0 100  interval_lt - ));
 DESCR("less-than");
-DATA(insert OID = 1165 (  timespan_le     PGUID 11 f t f 2 f 16 "1186 1186" 100 0 0 100  timespan_le - ));
+DATA(insert OID = 1165 (  interval_le     PGUID 11 f t f 2 f 16 "1186 1186" 100 0 0 100  interval_le - ));
 DESCR("less-than-or-equal");
-DATA(insert OID = 1166 (  timespan_ge     PGUID 11 f t f 2 f 16 "1186 1186" 100 0 0 100  timespan_ge - ));
+DATA(insert OID = 1166 (  interval_ge     PGUID 11 f t f 2 f 16 "1186 1186" 100 0 0 100  interval_ge - ));
 DESCR("greater-than-or-equal");
-DATA(insert OID = 1167 (  timespan_gt     PGUID 11 f t f 2 f 16 "1186 1186" 100 0 0 100  timespan_gt - ));
+DATA(insert OID = 1167 (  interval_gt     PGUID 11 f t f 2 f 16 "1186 1186" 100 0 0 100  interval_gt - ));
 DESCR("greater-than");
-DATA(insert OID = 1168 (  timespan_um     PGUID 11 f t f 1 f 1186 "1186" 100 0 0 100  timespan_um - ));
+DATA(insert OID = 1168 (  interval_um     PGUID 11 f t f 1 f 1186 "1186" 100 0 0 100  interval_um - ));
 DESCR("subtract");
-DATA(insert OID = 1169 (  timespan_pl    PGUID 11 f t f 2 f 1186 "1186 1186" 100 0 0 100  timespan_pl - ));
+DATA(insert OID = 1169 (  interval_pl    PGUID 11 f t f 2 f 1186 "1186 1186" 100 0 0 100  interval_pl - ));
 DESCR("addition");
-DATA(insert OID = 1170 (  timespan_mi    PGUID 11 f t f 2 f 1186 "1186 1186" 100 0 0 100  timespan_mi - ));
+DATA(insert OID = 1170 (  interval_mi    PGUID 11 f t f 2 f 1186 "1186 1186" 100 0 0 100  interval_mi - ));
 DESCR("subtract");
-DATA(insert OID = 1171 (  datetime_part    PGUID 11 f t f 2 f  701 "25 1184" 100 0 0 100  datetime_part - ));
-DESCR("extract field from datetime");
-DATA(insert OID = 1172 (  timespan_part    PGUID 11 f t f 2 f  701 "25 1186" 100 0 0 100  timespan_part - ));
-DESCR("extract field from timespan");
-
-DATA(insert OID = 1173 (  abstime_datetime      PGUID 11 f t f 1 f 1184  "702" 100 0 0 100  abstime_datetime - ));
-DESCR("convert abstime to datetime");
-DATA(insert OID = 1174 (  date_datetime                 PGUID 11 f t f 1 f 1184 "1082" 100 0 0 100  date_datetime - ));
-DESCR("convert date to datetime");
-DATA(insert OID = 1175 (  timestamp_datetime PGUID 11 f t f 1 f 1184 "1296" 100 0 0 100  timestamp_datetime - ));
-DESCR("convert timestamp to datetime");
-DATA(insert OID = 1176 (  datetime_datetime  PGUID 11 f t f 2 f 1184 "1082 1083" 100 0 0 100  datetime_datetime - ));
-DESCR("convert date and time to datetime");
-DATA(insert OID = 1177 (  reltime_timespan      PGUID 11 f t f 1 f 1186  "703" 100 0 0 100  reltime_timespan - ));
-DESCR("convert reltime to timespan");
-DATA(insert OID = 1178 (  datetime_date                 PGUID 11 f t f 1 f 1082 "1184" 100 0 0 100  datetime_date - ));
-DESCR("convert datetime to date");
+DATA(insert OID = 1171 (  timestamp_part    PGUID 11 f t f 2 f  701 "25 1184" 100 0 0 100  timestamp_part - ));
+DESCR("extract field from timestamp");
+DATA(insert OID = 1172 (  interval_part    PGUID 11 f t f 2 f  701 "25 1186" 100 0 0 100  interval_part - ));
+DESCR("extract field from interval");
+
+DATA(insert OID = 1173 (  abstime_timestamp     PGUID 11 f t f 1 f 1184  "702" 100 0 0 100  abstime_timestamp - ));
+DESCR("convert abstime to timestamp");
+DATA(insert OID = 1174 (  date_timestamp                PGUID 11 f t f 1 f 1184 "1082" 100 0 0 100  date_timestamp - ));
+DESCR("convert date to timestamp");
+DATA(insert OID = 1176 (  datetime_timestamp  PGUID 11 f t f 2 f 1184 "1082 1083" 100 0 0 100  datetime_timestamp - ));
+DESCR("convert date and time to timestamp");
+DATA(insert OID = 1177 (  reltime_interval      PGUID 11 f t f 1 f 1186  "703" 100 0 0 100  reltime_interval - ));
+DESCR("convert reltime to interval");
+DATA(insert OID = 1178 (  timestamp_date                PGUID 11 f t f 1 f 1082 "1184" 100 0 0 100  timestamp_date - ));
+DESCR("convert timestamp to date");
 DATA(insert OID = 1179 (  abstime_date          PGUID 11 f t f 1 f 1082  "702" 100 0 0 100  abstime_date - ));
 DESCR("convert abstime to date");
-DATA(insert OID = 1180 (  datetime_abstime      PGUID 11 f t f 1 f  702 "1184" 100 0 0 100  datetime_abstime - ));
-DESCR("convert datetime to abstime");
+DATA(insert OID = 1180 (  timestamp_abstime     PGUID 11 f t f 1 f  702 "1184" 100 0 0 100  timestamp_abstime - ));
+DESCR("convert timestamp to abstime");
 
-DATA(insert OID = 1188 (  datetime_mi          PGUID 11 f t f 2 f 1186 "1184 1184" 100 0 0 100  datetime_mi - ));
+DATA(insert OID = 1188 (  timestamp_mi         PGUID 11 f t f 2 f 1186 "1184 1184" 100 0 0 100  timestamp_mi - ));
 DESCR("subtract");
-DATA(insert OID = 1189 (  datetime_pl_span     PGUID 11 f t f 2 f 1184 "1184 1186" 100 0 0 100  datetime_pl_span - ));
+DATA(insert OID = 1189 (  timestamp_pl_span    PGUID 11 f t f 2 f 1184 "1184 1186" 100 0 0 100  timestamp_pl_span - ));
 DESCR("plus");
-DATA(insert OID = 1190 (  datetime_mi_span     PGUID 11 f t f 2 f 1184 "1184 1186" 100 0 0 100  datetime_mi_span - ));
+DATA(insert OID = 1190 (  timestamp_mi_span    PGUID 11 f t f 2 f 1184 "1184 1186" 100 0 0 100  timestamp_mi_span - ));
 DESCR("minus");
-DATA(insert OID = 1191 (  text_datetime                 PGUID 11 f t f 1 f 1184 "25" 100 0 0 100  text_datetime - ));
-DESCR("convert text to datetime");
-DATA(insert OID = 1192 (  datetime_text                 PGUID 11 f t f 1 f   25 "1184" 100 0 0 100  datetime_text - ));
-DESCR("convert datetime to text");
-DATA(insert OID = 1193 (  timespan_text                 PGUID 11 f t f 1 f   25 "1186" 100 0 0 100  timespan_text - ));
-DESCR("convert timespan to text");
-DATA(insert OID = 1194 (  timespan_reltime      PGUID 11 f t f 1 f  703 "1186" 100 0 0 100  timespan_reltime - ));
-DESCR("convert timespan to reltime");
-DATA(insert OID = 1195 (  datetime_smaller      PGUID 11 f t f 2 f 1184 "1184 1184" 100 0 0 100  datetime_smaller - ));
+DATA(insert OID = 1191 (  text_timestamp                PGUID 11 f t f 1 f 1184 "25" 100 0 0 100  text_timestamp - ));
+DESCR("convert text to timestamp");
+DATA(insert OID = 1192 (  timestamp_text                PGUID 11 f t f 1 f   25 "1184" 100 0 0 100  timestamp_text - ));
+DESCR("convert timestamp to text");
+DATA(insert OID = 1193 (  interval_text                 PGUID 11 f t f 1 f   25 "1186" 100 0 0 100  interval_text - ));
+DESCR("convert interval to text");
+DATA(insert OID = 1194 (  interval_reltime      PGUID 11 f t f 1 f  703 "1186" 100 0 0 100  interval_reltime - ));
+DESCR("convert interval to reltime");
+DATA(insert OID = 1195 (  timestamp_smaller     PGUID 11 f t f 2 f 1184 "1184 1184" 100 0 0 100  timestamp_smaller - ));
 DESCR("smaller of two");
-DATA(insert OID = 1196 (  datetime_larger       PGUID 11 f t f 2 f 1184 "1184 1184" 100 0 0 100  datetime_larger - ));
+DATA(insert OID = 1196 (  timestamp_larger      PGUID 11 f t f 2 f 1184 "1184 1184" 100 0 0 100  timestamp_larger - ));
 DESCR("larger of two");
-DATA(insert OID = 1197 (  timespan_smaller      PGUID 11 f t f 2 f 1186 "1186 1186" 100 0 0 100  timespan_smaller - ));
+DATA(insert OID = 1197 (  interval_smaller      PGUID 11 f t f 2 f 1186 "1186 1186" 100 0 0 100  interval_smaller - ));
 DESCR("smaller of two");
-DATA(insert OID = 1198 (  timespan_larger       PGUID 11 f t f 2 f 1186 "1186 1186" 100 0 0 100  timespan_larger - ));
+DATA(insert OID = 1198 (  interval_larger       PGUID 11 f t f 2 f 1186 "1186 1186" 100 0 0 100  interval_larger - ));
 DESCR("larger of two");
-DATA(insert OID = 1199 (  datetime_age          PGUID 11 f t f 2 f 1186 "1184 1184" 100 0 0 100  datetime_age - ));
+DATA(insert OID = 1199 (  timestamp_age                 PGUID 11 f t f 2 f 1186 "1184 1184" 100 0 0 100  timestamp_age - ));
 DESCR("date difference preserving months and years");
 
 /* OIDS 1200 - 1299 */
@@ -1492,10 +1490,10 @@ DESCR("date difference preserving months and years");
 DATA(insert OID = 1200 (  int4reltime     PGUID 11 f t t 1 f  703 "23" 100 0 0 100  int4reltime - ));
 DESCR("convert int4 to reltime");
 
-DATA(insert OID = 1217 (  datetime_trunc   PGUID 11 f t f 2 f 1184 "25 1184" 100 0 0 100  datetime_trunc - ));
-DESCR("truncate datetime to specified units");
-DATA(insert OID = 1218 (  timespan_trunc   PGUID 11 f t f 2 f 1186 "25 1186" 100 0 0 100  timespan_trunc - ));
-DESCR("truncate timespan to specified units");
+DATA(insert OID = 1217 (  timestamp_trunc   PGUID 11 f t f 2 f 1184 "25 1184" 100 0 0 100  timestamp_trunc - ));
+DESCR("truncate timestamp to specified units");
+DATA(insert OID = 1218 (  interval_trunc   PGUID 11 f t f 2 f 1186 "25 1186" 100 0 0 100  interval_trunc - ));
+DESCR("truncate interval to specified units");
 
 DATA(insert OID = 1230 (  bpchar                  PGUID 11 f t t 1 f 1042 "18" 100 0 0 100  char_bpchar - ));
 DESCR("convert char to char()");
@@ -1523,9 +1521,9 @@ DESCR("character length");
 DATA(insert OID = 1379 (  varcharoctetlen  PGUID 11 f t t 1 f 23 "1043" 100 0 0 100  varcharoctetlen - ));
 DESCR("octet length");
 
-DATA(insert OID = 1263 (  text_timespan    PGUID 11 f t f 1 f 1186 "25" 100 0 0 100  text_timespan - ));
-DESCR("convert text to timespan");
-DATA(insert OID = 1271 (  timespan_finite  PGUID 11 f t f 1 f  16 "1186" 100 0 0 100  timespan_finite - ));
+DATA(insert OID = 1263 (  text_interval    PGUID 11 f t f 1 f 1186 "25" 100 0 0 100  text_interval - ));
+DESCR("convert text to interval");
+DATA(insert OID = 1271 (  interval_finite  PGUID 11 f t f 1 f  16 "1186" 100 0 0 100  interval_finite - ));
 DESCR("boolean test");
 
 DATA(insert OID = 1274 (  int84pl                 PGUID 11 f t t 2 f 20 "20 23" 100 0 0 100  int84pl - ));
@@ -1562,44 +1560,26 @@ DESCR("latest tid of a tuple");
 DATA(insert OID = 1294 ( currtid2                 PGUID 11 f t f 2 f 27 "25 27" 100 0 0 100  currtid_byrelname - ));
 DESCR("latest tid of a tuple");
 
-DATA(insert OID = 1297 (  timestamp_in    PGUID 11 f t f 1 f 1296 "0" 100 0 0 100      timestamp_in - ));
-DESCR("(internal)");
-DATA(insert OID = 1298 (  timestamp_out    PGUID 11 f t f 1 f  23 "0" 100 0 0 100      timestamp_out - ));
-DESCR("(internal)");
-DATA(insert OID = 1299 (  now                     PGUID 11 f t f 0 f 1296 "0" 100 0 0 100      now - ));
+DATA(insert OID = 1299 (  now                     PGUID 11 f t f 0 f 1184 "0" 100 0 0 100      now - ));
 DESCR("current transaction time");
 
 /* OIDS 1300 - 1399 */
 
-DATA(insert OID = 1306 (  timestampeq           PGUID 11 f t t 2 f   16 "1296 1296" 100 0 0 100  timestampeq - ));
-DESCR("equal");
-DATA(insert OID = 1307 (  timestampne           PGUID 11 f t t 2 f   16 "1296 1296" 100 0 0 100  timestampne - ));
-DESCR("not equal");
-DATA(insert OID = 1308 (  timestamplt           PGUID 11 f t t 2 f   16 "1296 1296" 100 0 0 100  timestamplt - ));
-DESCR("less-than");
-DATA(insert OID = 1309 (  timestampgt           PGUID 11 f t t 2 f   16 "1296 1296" 100 0 0 100  timestampgt - ));
-DESCR("greater-than");
-DATA(insert OID = 1310 (  timestample           PGUID 11 f t t 2 f   16 "1296 1296" 100 0 0 100  timestample - ));
-DESCR("less-than-or-equal");
-DATA(insert OID = 1311 (  timestampge           PGUID 11 f t t 2 f   16 "1296 1296" 100 0 0 100  timestampge - ));
-DESCR("greater-than-or-equal");
-DATA(insert OID = 1314 (  datetime_cmp          PGUID 11 f t f 2 f   23 "1184 1184" 100 0 0 100  datetime_cmp - ));
+DATA(insert OID = 1314 (  timestamp_cmp                 PGUID 11 f t f 2 f   23 "1184 1184" 100 0 0 100  timestamp_cmp - ));
 DESCR("less-equal-greater");
-DATA(insert OID = 1315 (  timespan_cmp          PGUID 11 f t f 2 f   23 "1186 1186" 100 0 0 100  timespan_cmp - ));
+DATA(insert OID = 1315 (  interval_cmp          PGUID 11 f t f 2 f   23 "1186 1186" 100 0 0 100  interval_cmp - ));
 DESCR("less-equal-greater");
-DATA(insert OID = 1316 (  datetime_time                 PGUID 11 f t f 1 f 1083 "1184" 100 0 0 100  datetime_time - ));
-DESCR("convert datetime to time");
-DATA(insert OID = 1318 (  datetime_timestamp PGUID 11 f t f 1 f 1296 "1184" 100 0 0 100  datetime_timestamp - ));
-DESCR("convert datetime to timestamp");
-DATA(insert OID = 1326 (  timespan_div          PGUID 11 f t f 2 f 1186 "1186 701" 100 0 0 100  timespan_div - ));
+DATA(insert OID = 1316 (  timestamp_time                PGUID 11 f t f 1 f 1083 "1184" 100 0 0 100  timestamp_time - ));
+DESCR("convert timestamp to time");
+DATA(insert OID = 1326 (  interval_div          PGUID 11 f t f 2 f 1186 "1186 701" 100 0 0 100  interval_div - ));
 DESCR("divide");
 
-DATA(insert OID = 1339 (  date_zone                     PGUID 11 f t f 2 f   25 "25 1184" 100 0 0 100  datetime_zone - ));
+DATA(insert OID = 1339 (  date_zone                     PGUID 11 f t f 2 f   25 "25 1184" 100 0 0 100  timestamp_zone - ));
 DESCR("");
-DATA(insert OID = 1340 (  text                          PGUID 11 f t f 1 f   25 "1184" 100 0 0 100  datetime_text - ));
-DESCR("convert datetime to text");
-DATA(insert OID = 1341 (  text                          PGUID 11 f t f 1 f   25 "1186" 100 0 0 100  timespan_text - ));
-DESCR("convert timespan to text");
+DATA(insert OID = 1340 (  text                          PGUID 11 f t f 1 f   25 "1184" 100 0 0 100  timestamp_text - ));
+DESCR("convert timestamp to text");
+DATA(insert OID = 1341 (  text                          PGUID 11 f t f 1 f   25 "1186" 100 0 0 100  interval_text - ));
+DESCR("convert interval to text");
 DATA(insert OID = 1342 (  text                          PGUID 11 f t t 1 f   25 "23" 100 0 0 100  int4_text - ));
 DESCR("convert int4 to text");
 DATA(insert OID = 1343 (  text                          PGUID 11 f t t 1 f   25 "21" 100 0 0 100  int2_text - ));
@@ -1617,48 +1597,42 @@ DESCR("get description for object id");
 DATA(insert OID = 1349 (  oidvectortypes        PGUID 11 f t f 1 f   25 "30" 100 0 0 100  oidvectortypes - ));
 DESCR("print type names of oidvector field");
 
-DATA(insert OID = 1350 (  datetime                      PGUID 14 f t f 1 f 1184 "1184" 100 0 0 100  "select $1" - ));
+DATA(insert OID = 1350 (  timestamp                     PGUID 14 f t f 1 f 1184 "1184" 100 0 0 100  "select $1" - ));
 DESCR("convert (noop)");
-DATA(insert OID = 1351 (  datetime                      PGUID 11 f t f 1 f 1184 "25" 100 0 0 100  text_datetime - ));
-DESCR("convert text to datetime");
-DATA(insert OID = 1352 (  datetime                      PGUID 11 f t f 1 f 1184 "702" 100 0 0 100      abstime_datetime - ));
-DESCR("convert abstime to datetime");
-DATA(insert OID = 1353 (  datetime                      PGUID 11 f t f 1 f 1184 "1082" 100 0 0 100  date_datetime - ));
-DESCR("convert date to datetime");
-DATA(insert OID = 1354 (  datetime                      PGUID 11 f t f 1 f 1184 "1296" 100 0 0 100  timestamp_datetime - ));
-DESCR("convert timestamp to datetime");
-DATA(insert OID = 1355 (  datetime                      PGUID 11 f t f 2 f 1184 "1082 1083" 100 0 0 100  datetime_datetime - ));
-DESCR("convert date and time to datetime");
-DATA(insert OID = 1356 (  timespan                      PGUID 14 f t t 1 f 1186 "1186" 100 0 0 100  "select $1" - ));
+DATA(insert OID = 1351 (  timestamp                     PGUID 11 f t f 1 f 1184 "25" 100 0 0 100  text_timestamp - ));
+DESCR("convert text to timestamp");
+DATA(insert OID = 1352 (  timestamp                     PGUID 11 f t f 1 f 1184 "702" 100 0 0 100      abstime_timestamp - ));
+DESCR("convert abstime to timestamp");
+DATA(insert OID = 1353 (  timestamp                     PGUID 11 f t f 1 f 1184 "1082" 100 0 0 100  date_timestamp - ));
+DESCR("convert date to timestamp");
+DATA(insert OID = 1355 (  timestamp                     PGUID 11 f t f 2 f 1184 "1082 1083" 100 0 0 100  datetime_timestamp - ));
+DESCR("convert date and time to timestamp");
+DATA(insert OID = 1356 (  interval                      PGUID 14 f t t 1 f 1186 "1186" 100 0 0 100  "select $1" - ));
 DESCR("convert (noop)");
-DATA(insert OID = 1357 (  timespan                      PGUID 11 f t f 1 f 1186 "703" 100 0 0 100      reltime_timespan - ));
-DESCR("convert reltime to timespan");
-DATA(insert OID = 1358 (  timespan                      PGUID 14 f t f 1 f 1186 "1083" 100 0 0 100  "select time_timespan($1)" - ));
-DESCR("convert time to timespan");
+DATA(insert OID = 1357 (  interval                      PGUID 11 f t f 1 f 1186 "703" 100 0 0 100      reltime_interval - ));
+DESCR("convert reltime to interval");
+DATA(insert OID = 1358 (  interval                      PGUID 14 f t f 1 f 1186 "1083" 100 0 0 100  "select time_interval($1)" - ));
+DESCR("convert time to interval");
 DATA(insert OID = 1359 (  date                          PGUID 14 f t t 1 f 1082 "1082" 100 0 0 100  "select $1" - ));
 DESCR("convert (noop)");
-DATA(insert OID = 1360 (  date                          PGUID 11 f t f 1 f 1082 "1184" 100 0 0 100  datetime_date - ));
-DESCR("convert datetime to date");
+DATA(insert OID = 1360 (  date                          PGUID 11 f t f 1 f 1082 "1184" 100 0 0 100  timestamp_date - ));
+DESCR("convert timestamp to date");
 DATA(insert OID = 1361 (  date                          PGUID 11 f t f 1 f 1082 "702" 100 0 0 100      abstime_date - ));
 DESCR("convert abstime to date");
 DATA(insert OID = 1362 (  time                          PGUID 14 f t t 1 f 1083 "1083" 100 0 0 100  "select $1" - ));
 DESCR("convert (noop)");
-DATA(insert OID = 1363 (  time                          PGUID 11 f t f 1 f 1083 "1184" 100 0 0 100  datetime_time - ));
-DESCR("convert datetime to time");
-DATA(insert OID = 1364 (  time                          PGUID 14 f t f 1 f 1083 "702" 100 0 0 100      "select time(datetime($1))" - ));
+DATA(insert OID = 1363 (  time                          PGUID 11 f t f 1 f 1083 "1184" 100 0 0 100  timestamp_time - ));
+DESCR("convert timestamp to time");
+DATA(insert OID = 1364 (  time                          PGUID 14 f t f 1 f 1083 "702" 100 0 0 100      "select time(timestamp($1))" - ));
 DESCR("convert abstime to time");
 DATA(insert OID = 1365 (  abstime                       PGUID 14 f t f 1 f  702 "702" 100 0 0 100      "select $1" - ));
 DESCR("convert (noop)");
-DATA(insert OID = 1366 (  abstime                       PGUID 11 f t f 1 f  702 "1184" 100 0 0 100  datetime_abstime - ));
-DESCR("convert datetime to abstime");
+DATA(insert OID = 1366 (  abstime                       PGUID 11 f t f 1 f  702 "1184" 100 0 0 100  timestamp_abstime - ));
+DESCR("convert timestamp to abstime");
 DATA(insert OID = 1367 (  reltime                       PGUID 14 f t t 1 f  703 "703" 100 0 0 100      "select $1" - ));
 DESCR("convert (noop)");
-DATA(insert OID = 1368 (  reltime                       PGUID 11 f t f 1 f  703 "1186" 100 0 0 100  timespan_reltime - ));
-DESCR("convert timespan to reltime");
-DATA(insert OID = 1369 (  timestamp                     PGUID 14 f t t 1 f 1296 "1296" 100 0 0 100  "select $1" - ));
-DESCR("convert (noop)");
-DATA(insert OID = 1370 (  timestamp                     PGUID 11 f t f 1 f 1296 "1184" 100 0 0 100  datetime_timestamp - ));
-DESCR("convert datetime to timestamp");
+DATA(insert OID = 1368 (  reltime                       PGUID 11 f t f 1 f  703 "1186" 100 0 0 100  interval_reltime - ));
+DESCR("convert interval to reltime");
 DATA(insert OID = 1371 (  length                        PGUID 11 f t t 1 f   23   "25" 100 0 0 100  textlen - ));
 DESCR("character length");
 DATA(insert OID = 1372 (  length                        PGUID 11 f t t 1 f   23   "1042" 100 0 0 100  bpcharlen - ));
@@ -1673,36 +1647,36 @@ DESCR("octet length");
 DATA(insert OID = 1376 (  octet_length                  PGUID 11 f t t 1 f   23   "1043" 100 0 0 100  varcharoctetlen - ));
 DESCR("octet length");
 
-DATA(insert OID = 1380 (  date_part    PGUID 11 f t f 2 f  701 "25 1184" 100 0 0 100  datetime_part - ));
-DESCR("extract field from datetime");
-DATA(insert OID = 1381 (  date_part    PGUID 11 f t f 2 f  701 "25 1186" 100 0 0 100  timespan_part - ));
-DESCR("extract field from timespan");
-DATA(insert OID = 1382 (  date_part    PGUID 14 f t f 2 f  701 "25 702" 100 0 0 100  "select datetime_part($1, datetime($2))" - ));
+DATA(insert OID = 1380 (  date_part    PGUID 11 f t f 2 f  701 "25 1184" 100 0 0 100  timestamp_part - ));
+DESCR("extract field from timestamp");
+DATA(insert OID = 1381 (  date_part    PGUID 11 f t f 2 f  701 "25 1186" 100 0 0 100  interval_part - ));
+DESCR("extract field from interval");
+DATA(insert OID = 1382 (  date_part    PGUID 14 f t f 2 f  701 "25 702" 100 0 0 100  "select timestamp_part($1, timestamp($2))" - ));
 DESCR("extract field from abstime");
-DATA(insert OID = 1383 (  date_part    PGUID 14 f t f 2 f  701 "25 703" 100 0 0 100  "select timespan_part($1, timespan($2))" - ));
+DATA(insert OID = 1383 (  date_part    PGUID 14 f t f 2 f  701 "25 703" 100 0 0 100  "select interval_part($1, interval($2))" - ));
 DESCR("extract field from reltime");
-DATA(insert OID = 1384 (  date_part    PGUID 14 f t f 2 f  701 "25 1082" 100 0 0 100  "select datetime_part($1, datetime($2))" - ));
+DATA(insert OID = 1384 (  date_part    PGUID 14 f t f 2 f  701 "25 1082" 100 0 0 100  "select timestamp_part($1, timestamp($2))" - ));
 DESCR("extract field from date");
-DATA(insert OID = 1385 (  date_part    PGUID 14 f t f 2 f  701 "25 1083" 100 0 0 100  "select timespan_part($1, timespan($2))" - ));
+DATA(insert OID = 1385 (  date_part    PGUID 14 f t f 2 f  701 "25 1083" 100 0 0 100  "select interval_part($1, interval($2))" - ));
 DESCR("extract field from time");
-DATA(insert OID = 1386 (  date_trunc   PGUID 11 f t f 2 f 1184 "25 1184" 100 0 0 100  datetime_trunc - ));
-DESCR("truncate datetime to field");
-DATA(insert OID = 1387 (  date_trunc   PGUID 11 f t f 2 f 1186 "25 1186" 100 0 0 100  timespan_trunc - ));
-DESCR("truncate timespan to field");
-DATA(insert OID = 1388 (  age             PGUID 11 f t f 2 f 1186 "1184 1184" 100 0 0 100      datetime_age - ));
-DESCR("difference between datetimes but leave years and months unresolved");
-DATA(insert OID = 1389 (  age             PGUID 14 f t f 1 f 1186 "1184" 100 0 0 100  "select datetime_age(\'today\', $1)" - ));
-DESCR("difference between datetime and today but leave years and months unresolved");
-
-DATA(insert OID = 1390 (  isfinite        PGUID 11 f t f 1 f   16 "1184" 100 0 0 100  datetime_finite - ));
+DATA(insert OID = 1386 (  date_trunc   PGUID 11 f t f 2 f 1184 "25 1184" 100 0 0 100  timestamp_trunc - ));
+DESCR("truncate timestamp to field");
+DATA(insert OID = 1387 (  date_trunc   PGUID 11 f t f 2 f 1186 "25 1186" 100 0 0 100  interval_trunc - ));
+DESCR("truncate interval to field");
+DATA(insert OID = 1388 (  age             PGUID 11 f t f 2 f 1186 "1184 1184" 100 0 0 100      timestamp_age - ));
+DESCR("difference between timestamps but leave years and months unresolved");
+DATA(insert OID = 1389 (  age             PGUID 14 f t f 1 f 1186 "1184" 100 0 0 100  "select timestamp_age(\'today\', $1)" - ));
+DESCR("difference between timestamp and today but leave years and months unresolved");
+
+DATA(insert OID = 1390 (  isfinite        PGUID 11 f t f 1 f   16 "1184" 100 0 0 100  timestamp_finite - ));
 DESCR("boolean test");
-DATA(insert OID = 1391 (  isfinite        PGUID 11 f t f 1 f   16 "1186" 100 0 0 100  timespan_finite - ));
+DATA(insert OID = 1391 (  isfinite        PGUID 11 f t f 1 f   16 "1186" 100 0 0 100  interval_finite - ));
 DESCR("boolean test");
 DATA(insert OID = 1392 (  isfinite        PGUID 11 f t f 1 f   16 "702" 100 0 0 100  abstime_finite - ));
 DESCR("boolean test");
 
-DATA(insert OID = 1393 (  timespan        PGUID 11 f t f 1 f 1186 "25" 100 0 0 100  text_timespan - ));
-DESCR("convert text to timespan");
+DATA(insert OID = 1393 (  interval        PGUID 11 f t f 1 f 1186 "25" 100 0 0 100  text_interval - ));
+DESCR("convert text to interval");
 
 DATA(insert OID = 1394 (  name            PGUID 11 f t t 1 f   19 "25" 100 0 0 100  text_name - ));
 DESCR("convert text to name");
@@ -2352,9 +2326,7 @@ DATA(insert OID = 1769 ( numeric_cmp                      PGUID 11 f t t 2 f 23 "1700 1700" 100 0 0
 DESCR("compare two numbers");
 
 /* formatting */
-DATA(insert OID = 1770 ( to_char                       PGUID 11 f t f 2 f  25 "1184 25" 100 0 0 100  datetime_to_char - ));
-DESCR("convert / formatting datetime to text");
-DATA(insert OID = 1771 ( to_char                       PGUID 11 f t f 2 f  25 "1296 25" 100 0 0 100  timestamp_to_char - ));
+DATA(insert OID = 1770 ( to_char                       PGUID 11 f t f 2 f  25 "1184 25" 100 0 0 100  timestamp_to_char - ));
 DESCR("convert / formatting timestamp to text");
 DATA(insert OID = 1772 ( to_char                       PGUID 11 f t f 2 f  25 "1700 25" 100 0 0 100  numeric_to_char - ));
 DESCR("convert / formatting numeric to text");
@@ -2368,10 +2340,8 @@ DATA(insert OID = 1776 ( to_char                 PGUID 11 f t f 2 f  25 "701 25" 100 0 0 100
 DESCR("convert / formatting float8 to text");
 DATA(insert OID = 1777 ( to_number                     PGUID 11 f t f 2 f  1700 "25 25" 100 0 0 100  numeric_to_number - ));
 DESCR("convert text to numeric");
-DATA(insert OID = 1778 ( to_datetime                   PGUID 11 f t f 2 f  1184 "25 25" 100 0 0 100  to_datetime - ));
-DESCR("convert text to datetime");
-DATA(insert OID = 1779 ( to_timestamp                  PGUID 11 f t f 2 f  1296 "25 25" 100 0 0 100  to_timestamp - ));
-DESCR("convert text to datetime");
+DATA(insert OID = 1778 ( to_timestamp                  PGUID 11 f t f 2 f  1184 "25 25" 100 0 0 100  to_timestamp - ));
+DESCR("convert text to timestamp");
 DATA(insert OID = 1780 ( to_date                       PGUID 11 f t f 2 f  1082 "25 25" 100 0 0 100  to_date - ));
 DESCR("convert text to date");
 
index b22c80e0f0b88e0ef8d56d02378a642c0f14c935..fa074460a7fd973a465ecdfde68f08a6c5e90050 100644 (file)
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_type.h,v 1.80 2000/02/15 03:28:31 thomas Exp $
+ * $Id: pg_type.h,v 1.81 2000/02/16 17:26:07 thomas Exp $
  *
  * NOTES
  *       the genbki.sh script reads this file and generates .bki
@@ -370,20 +370,17 @@ DESCR("hh:mm:ss, ANSI SQL time");
 /* OIDS 1100 - 1199 */
 DATA(insert OID = 1182 ( _date          PGUID  -1 -1 f b t \054 0      1082 array_in array_out array_in array_out i _null_ ));
 DATA(insert OID = 1183 ( _time          PGUID  -1 -1 f b t \054 0      1083 array_in array_out array_in array_out d _null_ ));
-DATA(insert OID = 1184 ( datetime       PGUID  8  47 f b t \054 0      0 datetime_in datetime_out datetime_in datetime_out d _null_ ));
+DATA(insert OID = 1184 ( timestamp      PGUID  8  47 f b t \054 0      0 timestamp_in timestamp_out timestamp_in timestamp_out d _null_ ));
 DESCR("date and time");
-#define DATETIMEOID            1184
-DATA(insert OID = 1185 ( _datetime      PGUID  -1 -1 f b t \054 0      1184 array_in array_out array_in array_out d _null_ ));
-DATA(insert OID = 1186 ( timespan       PGUID 12  47 f b t \054 0      0 timespan_in timespan_out timespan_in timespan_out d _null_ ));
+#define TIMESTAMPOID   1184
+DATA(insert OID = 1185 ( _timestamp     PGUID  -1 -1 f b t \054 0      1184 array_in array_out array_in array_out d _null_ ));
+DATA(insert OID = 1186 ( interval       PGUID 12  47 f b t \054 0      0 interval_in interval_out interval_in interval_out d _null_ ));
 DESCR("@ <number> <units>, time interval");
-#define TIMESPANOID            1186
-DATA(insert OID = 1187 ( _timespan      PGUID  -1 -1 f b t \054 0      1186 array_in array_out array_in array_out d _null_ ));
+#define INTERVALOID            1186
+DATA(insert OID = 1187 ( _interval      PGUID  -1 -1 f b t \054 0      1186 array_in array_out array_in array_out d _null_ ));
 
 /* OIDS 1200 - 1299 */
 DATA(insert OID = 1231 (  _numeric   PGUID -1  -1 f b t \054 0  1700 array_in array_out array_in array_out i _null_ ));
-DATA(insert OID = 1296 ( timestamp      PGUID  4  19 t b t \054 0      0 timestamp_in timestamp_out timestamp_in timestamp_out i _null_ ));
-DESCR("date time timezone, limited-range ISO-formated date and time");
-#define TIMESTAMPOID   1296
 
 /* OIDS 1700 - 1799 */
 DATA(insert OID = 1700 ( numeric          PGUID -1  -1 f b t \054 0  0 numeric_in numeric_out numeric_in numeric_out i _null_ ));
index bedaaa37bd9f7c20d1e598a9a90e9d91beb540c7..54107ef3b80c1082aa3d275078f4d5b486bf7841 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: parse_coerce.h,v 1.17 2000/01/26 05:58:27 momjian Exp $
+ * $Id: parse_coerce.h,v 1.18 2000/02/16 17:26:16 thomas Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -48,8 +48,9 @@ typedef enum CATEGORY
                || ((t) == INT4OID) \
                || ((t) == INT8OID) \
                || ((t) == FLOAT8OID) \
-               || ((t) == DATETIMEOID) \
+               || ((t) == NUMERICOID) \
                || ((t) == TIMESTAMPOID) \
+               || ((t) == INTERVALOID) \
                || ((t) == ABSTIMEOID) \
                || ((t) == RELTIMEOID) \
                || ((t) == CHAROID) \
@@ -70,8 +71,8 @@ typedef enum CATEGORY
  * Check for types with the same underlying binary representation.
  * This allows us to cheat and directly exchange values without
  *     going through the trouble of calling a conversion function.
- * Remove equivalencing of FLOAT8 and DATETIME. They really are not
- *     close enough in behavior, with the DATETIME reserved values
+ * Remove equivalencing of FLOAT8 and TIMESTAMP. They really are not
+ *     close enough in behavior, with the TIMESTAMP reserved values
  *     and special formatting. - thomas 1999-01-24
  */
 #define IS_BINARY_COMPATIBLE(a,b) \
@@ -87,12 +88,8 @@ typedef enum CATEGORY
                || ((a) == INT4OID && (b) == REGPROCOID) \
                || ((a) == REGPROCOID && (b) == OIDOID) \
                || ((a) == REGPROCOID && (b) == INT4OID) \
-               || ((a) == ABSTIMEOID && (b) == TIMESTAMPOID) \
                || ((a) == ABSTIMEOID && (b) == INT4OID) \
-               || ((a) == TIMESTAMPOID && (b) == ABSTIMEOID) \
-               || ((a) == TIMESTAMPOID && (b) == INT4OID) \
                || ((a) == INT4OID && (b) == ABSTIMEOID) \
-               || ((a) == INT4OID && (b) == TIMESTAMPOID) \
                || ((a) == RELTIMEOID && (b) == INT4OID) \
                || ((a) == INT4OID && (b) == RELTIMEOID) \
                || ((a) == INETOID && (b) == CIDROID) \
@@ -104,21 +101,21 @@ typedef enum CATEGORY
 #define IS_HIGHER_TYPE(t) \
                  (((t) == TEXTOID) \
                || ((t) == FLOAT8OID) \
-               || ((t) == TIMESPANOID) \
-               || ((t) == DATETIMEOID) \
+               || ((t) == INTERVALOID) \
+               || ((t) == TIMESTAMPOID) \
                || ((t) == POLYGONOID) \
                || ((t) == INETOID) )
 
 /* IS_HIGHEST_TYPE()
  * These types are the most general in each of the type categories.
- * Since timespan and datetime overload so many functions, let's
- *     give datetime the preference.
+ * Since interval and timestamp overload so many functions, let's
+ *     give timestamp the preference.
  * Since text is a generic string type let's leave it out too.
  */
 #define IS_HIGHEST_TYPE(t) \
                  (((t) == FLOAT8OID) \
-               || ((t) == DATETIMEOID) \
-               || ((t) == TIMESPANOID))
+               || ((t) == TIMESTAMPOID) \
+               || ((t) == INTERVALOID))
 
 
 extern bool IsPreferredType(CATEGORY category, Oid type);
index 7f9dcc6c4696757a93532358dadb7c947f717a95..df8dad8dc38479e5cb4ac719394023d55780861f 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: builtins.h,v 1.101 2000/02/15 20:49:27 tgl Exp $
+ * $Id: builtins.h,v 1.102 2000/02/16 17:26:25 thomas Exp $
  *
  * NOTES
  *       This should normally only be included by fmgr.h.
 #include "nodes/relation.h"            /* for amcostestimate parameters */
 #include "storage/itemptr.h"
 #include "utils/array.h"
-#include "utils/datetime.h"
-#include "utils/geo_decls.h"
 #include "utils/inet.h"
 #include "utils/int8.h"
-#include "utils/nabstime.h"
+#include "utils/geo_decls.h"
 #include "utils/numeric.h"
+#include "utils/datetime.h"
+#include "utils/timestamp.h"
+#include "utils/nabstime.h"
+#include "utils/date.h"
 
 /*
  *             Defined in adt/
@@ -204,46 +206,6 @@ extern int32 pqtest(struct varlena * vlena);
 
 /* arrayfuncs.c */
 
-/* date.c */
-extern RelativeTime reltimein(char *timestring);
-extern char *reltimeout(RelativeTime timevalue);
-extern TimeInterval tintervalin(char *intervalstr);
-extern char *tintervalout(TimeInterval interval);
-extern RelativeTime timespan_reltime(TimeSpan *timespan);
-extern TimeSpan *reltime_timespan(RelativeTime reltime);
-extern TimeInterval mktinterval(AbsoluteTime t1, AbsoluteTime t2);
-extern AbsoluteTime timepl(AbsoluteTime t1, RelativeTime t2);
-extern AbsoluteTime timemi(AbsoluteTime t1, RelativeTime t2);
-
-/* extern RelativeTime abstimemi(AbsoluteTime t1, AbsoluteTime t2);  static*/
-extern int     ininterval(AbsoluteTime t, TimeInterval interval);
-extern RelativeTime intervalrel(TimeInterval interval);
-extern AbsoluteTime timenow(void);
-extern bool reltimeeq(RelativeTime t1, RelativeTime t2);
-extern bool reltimene(RelativeTime t1, RelativeTime t2);
-extern bool reltimelt(RelativeTime t1, RelativeTime t2);
-extern bool reltimegt(RelativeTime t1, RelativeTime t2);
-extern bool reltimele(RelativeTime t1, RelativeTime t2);
-extern bool reltimege(RelativeTime t1, RelativeTime t2);
-extern bool intervalsame(TimeInterval i1, TimeInterval i2);
-extern bool intervaleq(TimeInterval i1, TimeInterval i2);
-extern bool intervalne(TimeInterval i1, TimeInterval i2);
-extern bool intervallt(TimeInterval i1, TimeInterval i2);
-extern bool intervalgt(TimeInterval i1, TimeInterval i2);
-extern bool intervalle(TimeInterval i1, TimeInterval i2);
-extern bool intervalge(TimeInterval i1, TimeInterval i2);
-extern bool intervalleneq(TimeInterval i, RelativeTime t);
-extern bool intervallenne(TimeInterval i, RelativeTime t);
-extern bool intervallenlt(TimeInterval i, RelativeTime t);
-extern bool intervallengt(TimeInterval i, RelativeTime t);
-extern bool intervallenle(TimeInterval i, RelativeTime t);
-extern bool intervallenge(TimeInterval i, RelativeTime t);
-extern bool intervalct(TimeInterval i1, TimeInterval i2);
-extern bool intervalov(TimeInterval i1, TimeInterval i2);
-extern AbsoluteTime intervalstart(TimeInterval i);
-extern AbsoluteTime intervalend(TimeInterval i);
-extern text *timeofday(void);
-
 /* filename.c */
 extern char *filename_in(char *file);
 extern char *filename_out(char *s);
@@ -326,9 +288,6 @@ extern bool float84le(float64 arg1, float32 arg2);
 extern bool float84gt(float64 arg1, float32 arg2);
 extern bool float84ge(float64 arg1, float32 arg2);
 
-/* geo_ops.c, geo_selfuncs.c */
-extern double *box_area(BOX *box);
-
 /* misc.c */
 extern bool nullvalue(Datum value, bool *isNull);
 extern bool nonnullvalue(Datum value, bool *isNull);
@@ -432,19 +391,6 @@ extern ItemPointer text_tid(const text *);
 extern ItemPointer currtid_byreloid(Oid relOid, ItemPointer); 
 extern ItemPointer currtid_byrelname(const text* relName, ItemPointer); 
 
-/* timestamp.c */
-extern time_t timestamp_in(const char *timestamp_str);
-extern char *timestamp_out(time_t timestamp);
-extern time_t now(void);
-bool           timestampeq(time_t t1, time_t t2);
-bool           timestampne(time_t t1, time_t t2);
-bool           timestamplt(time_t t1, time_t t2);
-bool           timestampgt(time_t t1, time_t t2);
-bool           timestample(time_t t1, time_t t2);
-bool           timestampge(time_t t1, time_t t2);
-DateTime   *timestamp_datetime(time_t timestamp);
-time_t         datetime_timestamp(DateTime *datetime);
-
 /* varchar.c */
 extern char *bpcharin(char *s, int dummy, int32 atttypmod);
 extern char *bpcharout(char *s);
@@ -508,38 +454,6 @@ extern int32 byteaGetBit(struct varlena * v, int32 n);
 extern struct varlena *byteaSetByte(struct varlena * v, int32 n, int32 newByte);
 extern struct varlena *byteaSetBit(struct varlena * v, int32 n, int32 newBit);
 
-/* datetime.c */
-extern DateADT date_in(char *datestr);
-extern char *date_out(DateADT dateVal);
-extern bool date_eq(DateADT dateVal1, DateADT dateVal2);
-extern bool date_ne(DateADT dateVal1, DateADT dateVal2);
-extern bool date_lt(DateADT dateVal1, DateADT dateVal2);
-extern bool date_le(DateADT dateVal1, DateADT dateVal2);
-extern bool date_gt(DateADT dateVal1, DateADT dateVal2);
-extern bool date_ge(DateADT dateVal1, DateADT dateVal2);
-extern int     date_cmp(DateADT dateVal1, DateADT dateVal2);
-extern DateADT date_larger(DateADT dateVal1, DateADT dateVal2);
-extern DateADT date_smaller(DateADT dateVal1, DateADT dateVal2);
-extern int32 date_mi(DateADT dateVal1, DateADT dateVal2);
-extern DateADT date_pli(DateADT dateVal, int32 days);
-extern DateADT date_mii(DateADT dateVal, int32 days);
-extern DateTime *date_datetime(DateADT date);
-extern DateADT datetime_date(DateTime *datetime);
-extern DateTime *datetime_datetime(DateADT date, TimeADT *time);
-extern DateADT abstime_date(AbsoluteTime abstime);
-
-extern TimeADT *time_in(char *timestr);
-extern char *time_out(TimeADT *time);
-extern bool time_eq(TimeADT *time1, TimeADT *time2);
-extern bool time_ne(TimeADT *time1, TimeADT *time2);
-extern bool time_lt(TimeADT *time1, TimeADT *time2);
-extern bool time_le(TimeADT *time1, TimeADT *time2);
-extern bool time_gt(TimeADT *time1, TimeADT *time2);
-extern bool time_ge(TimeADT *time1, TimeADT *time2);
-extern int     time_cmp(TimeADT *time1, TimeADT *time2);
-extern TimeADT *datetime_time(DateTime *datetime);
-extern int32 int4reltime(int32 timevalue);
-
 /* like.c */
 extern bool namelike(NameData *n, struct varlena * p);
 extern bool namenlike(NameData *s, struct varlena * p);
diff --git a/src/include/utils/date.h b/src/include/utils/date.h
new file mode 100644 (file)
index 0000000..003ee2e
--- /dev/null
@@ -0,0 +1,52 @@
+/*-------------------------------------------------------------------------
+ *
+ * date.h
+ *       Definitions for the SQL92 "date" and "time" types.
+ *
+ *
+ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * $Id: date.h,v 1.1 2000/02/16 17:26:26 thomas Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef DATE_H
+#define DATE_H
+
+typedef int32 DateADT;
+
+typedef float8 TimeADT;
+
+/* date.c */
+extern DateADT date_in(char *datestr);
+extern char *date_out(DateADT dateVal);
+extern bool date_eq(DateADT dateVal1, DateADT dateVal2);
+extern bool date_ne(DateADT dateVal1, DateADT dateVal2);
+extern bool date_lt(DateADT dateVal1, DateADT dateVal2);
+extern bool date_le(DateADT dateVal1, DateADT dateVal2);
+extern bool date_gt(DateADT dateVal1, DateADT dateVal2);
+extern bool date_ge(DateADT dateVal1, DateADT dateVal2);
+extern int     date_cmp(DateADT dateVal1, DateADT dateVal2);
+extern DateADT date_larger(DateADT dateVal1, DateADT dateVal2);
+extern DateADT date_smaller(DateADT dateVal1, DateADT dateVal2);
+extern int32 date_mi(DateADT dateVal1, DateADT dateVal2);
+extern DateADT date_pli(DateADT dateVal, int32 days);
+extern DateADT date_mii(DateADT dateVal, int32 days);
+extern Timestamp *date_timestamp(DateADT date);
+extern DateADT timestamp_date(Timestamp *timestamp);
+extern Timestamp *datetime_timestamp(DateADT date, TimeADT *time);
+extern DateADT abstime_date(AbsoluteTime abstime);
+
+extern TimeADT *time_in(char *timestr);
+extern char *time_out(TimeADT *time);
+extern bool time_eq(TimeADT *time1, TimeADT *time2);
+extern bool time_ne(TimeADT *time1, TimeADT *time2);
+extern bool time_lt(TimeADT *time1, TimeADT *time2);
+extern bool time_le(TimeADT *time1, TimeADT *time2);
+extern bool time_gt(TimeADT *time1, TimeADT *time2);
+extern bool time_ge(TimeADT *time1, TimeADT *time2);
+extern int     time_cmp(TimeADT *time1, TimeADT *time2);
+extern TimeADT *timestamp_time(Timestamp *timestamp);
+
+#endif  /* DATE_H */
index 2a97f5e0dd5730ccc2bb1d0b7ea5d57ce6fac723..3df9ddf19f0db468be6ab241606fddada3db7a9d 100644 (file)
 /*-------------------------------------------------------------------------
  *
  * datetime.h
- *       Definitions for the datetime
+ *       Definitions for the date/time and other date/time support code.
+ *       The support code is shared with other date data types,
+ *        including abstime, reltime, date, and time.
  *
  *
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: datetime.h,v 1.9 2000/01/26 05:58:37 momjian Exp $
+ * $Id: datetime.h,v 1.10 2000/02/16 17:26:26 thomas Exp $
  *
  *-------------------------------------------------------------------------
  */
 #ifndef DATETIME_H
 #define DATETIME_H
 
-typedef int32 DateADT;
+#include <time.h>
+#include <math.h>
+#include <limits.h>
+#include "utils/timestamp.h"
+
+#if 0
+
+
+/*
+ * Timestamp represents absolute time.
+ * TimeSpan represents delta time. Keep track of months (and years)
+ *     separately since the elapsed time spanned is unknown until instantiated
+ *     relative to an absolute time.
+ *
+ * Note that Postgres uses "time interval" to mean a bounded interval,
+ *     consisting of a beginning and ending time, not a time span - thomas 97/03/20
+ */
+
+typedef double Timestamp;
+
+typedef struct
+{
+       double          time;                   /* all time units other than months and
+                                                                * years */
+       int4            month;                  /* months and years, after time for
+                                                                * alignment */
+} TimeSpan;
+
+
+#endif
+
+
+/* ----------------------------------------------------------------
+ *                             time types + support macros
+ *
+ * String definitions for standard time quantities.
+ *
+ * These strings are the defaults used to form output time strings.
+ * Other alternate forms are hardcoded into token tables in datetime.c.
+ * ----------------------------------------------------------------
+ */
+
+#define DAGO                   "ago"
+#define DCURRENT               "current"
+#define EPOCH                  "epoch"
+#define INVALID                        "invalid"
+#define EARLY                  "-infinity"
+#define LATE                   "infinity"
+#define NOW                            "now"
+#define TODAY                  "today"
+#define TOMORROW               "tomorrow"
+#define YESTERDAY              "yesterday"
+#define ZULU                   "zulu"
+
+#define DMICROSEC              "usecond"
+#define DMILLISEC              "msecond"
+#define DSECOND                        "second"
+#define DMINUTE                        "minute"
+#define DHOUR                  "hour"
+#define DDAY                   "day"
+#define DWEEK                  "week"
+#define DMONTH                 "month"
+#define DQUARTER               "quarter"
+#define DYEAR                  "year"
+#define DDECADE                        "decade"
+#define DCENTURY               "century"
+#define DMILLENIUM             "millenium"
+#define DA_D                   "ad"
+#define DB_C                   "bc"
+#define DTIMEZONE              "timezone"
+
+/*
+ * Fundamental time field definitions for parsing.
+ *
+ *     Meridian:  am, pm, or 24-hour style.
+ *     Millenium: ad, bc
+ */
+
+#define AM             0
+#define PM             1
+#define HR24   2
+
+#define AD             0
+#define BC             1
+
+/*
+ * Fields for time decoding.
+ * Can't have more of these than there are bits in an unsigned int
+ *     since these are turned into bit masks during parsing and decoding.
+ */
+
+#define RESERV 0
+#define MONTH  1
+#define YEAR   2
+#define DAY            3
+#define TIMES  4                               /* not used - thomas 1997-07-14 */
+#define TZ             5
+#define DTZ            6
+#define DTZMOD 7
+#define IGNORE 8
+#define AMPM   9
+#define HOUR   10
+#define MINUTE 11
+#define SECOND 12
+#define DOY            13
+#define DOW            14
+#define UNITS  15
+#define ADBC   16
+/* these are only for relative dates */
+#define AGO            17
+#define ABS_BEFORE             18
+#define ABS_AFTER              19
+
+/*
+ * Token field definitions for time parsing and decoding.
+ * These need to fit into the datetkn table type.
+ * At the moment, that means keep them within [-127,127].
+ * These are also used for bit masks in DecodeDateDelta()
+ *     so actually restrict them to within [0,31] for now.
+ * - thomas 97/06/19
+ * Not all of these fields are used for masks in DecodeDateDelta
+ *     so allow some larger than 31. - thomas 1997-11-17
+ */
+
+#define DTK_NUMBER             0
+#define DTK_STRING             1
+
+#define DTK_DATE               2
+#define DTK_TIME               3
+#define DTK_TZ                 4
+#define DTK_AGO                        5
+
+#define DTK_SPECIAL            6
+#define DTK_INVALID            7
+#define DTK_CURRENT            8
+#define DTK_EARLY              9
+#define DTK_LATE               10
+#define DTK_EPOCH              11
+#define DTK_NOW                        12
+#define DTK_YESTERDAY  13
+#define DTK_TODAY              14
+#define DTK_TOMORROW   15
+#define DTK_ZULU               16
+
+#define DTK_DELTA              17
+#define DTK_SECOND             18
+#define DTK_MINUTE             19
+#define DTK_HOUR               20
+#define DTK_DAY                        21
+#define DTK_WEEK               22
+#define DTK_MONTH              23
+#define DTK_QUARTER            24
+#define DTK_YEAR               25
+#define DTK_DECADE             26
+#define DTK_CENTURY            27
+#define DTK_MILLENIUM  28
+#define DTK_MILLISEC   29
+#define DTK_MICROSEC   30
+
+#define DTK_DOW                        32
+#define DTK_DOY                        33
+#define DTK_TZ_HOUR            34
+#define DTK_TZ_MINUTE  35
+
+/*
+ * Bit mask definitions for time parsing.
+ */
+
+#define DTK_M(t)               (0x01 << (t))
+
+#define DTK_DATE_M             (DTK_M(YEAR) | DTK_M(MONTH) | DTK_M(DAY))
+#define DTK_TIME_M             (DTK_M(HOUR) | DTK_M(MINUTE) | DTK_M(SECOND))
+
+#define MAXDATELEN             47              /* maximum possible length of an input
+                                                                * date string */
+#define MAXDATEFIELDS  25              /* maximum possible number of fields in a
+                                                                * date string */
+#define TOKMAXLEN              10              /* only this many chars are stored in
+                                                                * datetktbl */
+
+/* keep this struct small; it gets used a lot */
+typedef struct
+{
+#if defined(_AIX)
+       char       *token;
+#else
+       char            token[TOKMAXLEN];
+#endif  /* _AIX */
+       char            type;
+       char            value;                  /* this may be unsigned, alas */
+} datetkn;
+
+
+#if 0
+
+
+#ifdef NAN
+#define TIMESTAMP_INVALID              (NAN)
+#else
+#define TIMESTAMP_INVALID              (DBL_MIN+DBL_MIN)
+#endif
+#ifdef HUGE_VAL
+#define TIMESTAMP_NOBEGIN              (-HUGE_VAL)
+#define TIMESTAMP_NOEND                (HUGE_VAL)
+#else
+#define TIMESTAMP_NOBEGIN              (-DBL_MAX)
+#define TIMESTAMP_NOEND                (DBL_MAX)
+#endif
+#define TIMESTAMP_CURRENT              (DBL_MIN)
+#define TIMESTAMP_EPOCH                (-DBL_MIN)
+
+#define TIMESTAMP_INVALID(j)           {j = TIMESTAMP_INVALID;}
+#ifdef NAN
+#define TIMESTAMP_IS_INVALID(j)        (isnan(j))
+#else
+#define TIMESTAMP_IS_INVALID(j)        (j == TIMESTAMP_INVALID)
+#endif
+
+#define TIMESTAMP_NOBEGIN(j)           {j = DT_NOBEGIN;}
+#define TIMESTAMP_IS_NOBEGIN(j)        (j == TIMESTAMP_NOBEGIN)
+
+#define TIMESTAMP_NOEND(j)             {j = TIMESTAMP_NOEND;}
+#define TIMESTAMP_IS_NOEND(j)  (j == TIMESTAMP_NOEND)
+
+#define TIMESTAMP_CURRENT(j)           {j = TIMESTAMP_CURRENT;}
+#if defined(linux) && defined(__powerpc__)
+extern int     timestamp_is_current(double j);
+
+#define TIMESTAMP_IS_CURRENT(j)        timestamp_is_current(j)
+#else
+#define TIMESTAMP_IS_CURRENT(j)        (j == TIMESTAMP_CURRENT)
+#endif
+
+#define TIMESTAMP_EPOCH(j)             {j = TIMESTAMP_EPOCH;}
+#if defined(linux) && defined(__powerpc__)
+extern int     timestamp_is_epoch(double j);
+
+#define TIMESTAMP_IS_EPOCH(j)  timestamp_is_epoch(j)
+#else
+#define TIMESTAMP_IS_EPOCH(j)  (j == TIMESTAMP_EPOCH)
+#endif
+
+#define TIMESTAMP_IS_RELATIVE(j) (TIMESTAMP_IS_CURRENT(j) || TIMESTAMP_IS_EPOCH(j))
+#define TIMESTAMP_NOT_FINITE(j)        (TIMESTAMP_IS_INVALID(j) \
+                                                               || TIMESTAMP_IS_NOBEGIN(j) || TIMESTAMP_IS_NOEND(j))
+#define TIMESTAMP_IS_RESERVED(j) (TIMESTAMP_IS_RELATIVE(j) || TIMESTAMP_NOT_FINITE(j))
+
+#define TIMESPAN_INVALID(j)            {(j).time = DT_INVALID;}
+#ifdef NAN
+#define TIMESPAN_IS_INVALID(j) (isnan((j).time))
+#else
+#define TIMESPAN_IS_INVALID(j) ((j).time == DATETIME_INVALID)
+#endif
+#define TIMESPAN_NOT_FINITE(j) TIMESPAN_IS_INVALID(j)
+
+#define TIME_PREC_INV 1000000.0
+#define JROUND(j) (rint(((double) (j))*TIME_PREC_INV)/TIME_PREC_INV)
+
+
+#endif
+
+/* TMODULO()
+ * Macro to replace modf(), which is broken on some platforms.
+ */
+#define TMODULO(t,q,u) \
+do { \
+       q = ((t < 0)? ceil(t / u): floor(t / u)); \
+       if (q != 0) \
+               t -= rint(q * u); \
+} while(0)
+
+
+/*
+ * Date/time validation
+ * Include check for leap year.
+ */
+
+extern int     day_tab[2][13];
+
+#define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
+
+/* Julian date support for date2j() and j2date()
+ * Set the minimum year to one greater than the year of the first valid day
+ *     to avoid having to check year and day both. - tgl 97/05/08
+ */
+
+#define JULIAN_MINYEAR (-4713)
+#define JULIAN_MINMONTH (11)
+#define JULIAN_MINDAY (23)
+
+#define IS_VALID_JULIAN(y,m,d) ((y > JULIAN_MINYEAR) \
+ || ((y == JULIAN_MINYEAR) && ((m > JULIAN_MINMONTH) \
+  || ((m == JULIAN_MINMONTH) && (d >= JULIAN_MINDAY)))))
+
+#define UTIME_MINYEAR (1901)
+#define UTIME_MINMONTH (12)
+#define UTIME_MINDAY (14)
+#define UTIME_MAXYEAR (2038)
+#define UTIME_MAXMONTH (01)
+#define UTIME_MAXDAY (18)
+
+#define IS_VALID_UTIME(y,m,d) (((y > UTIME_MINYEAR) \
+ || ((y == UTIME_MINYEAR) && ((m > UTIME_MINMONTH) \
+  || ((m == UTIME_MINMONTH) && (d >= UTIME_MINDAY))))) \
+ && ((y < UTIME_MAXYEAR) \
+ || ((y == UTIME_MAXYEAR) && ((m < UTIME_MAXMONTH) \
+  || ((m == UTIME_MAXMONTH) && (d <= UTIME_MAXDAY))))))
+
+
+#if 0
+
+
+/*
+ * datetime.c prototypes
+ */
+
+extern DateTime *datetime_in(char *str);
+extern char *datetime_out(DateTime *dt);
+extern bool datetime_eq(DateTime *dt1, DateTime *dt2);
+extern bool datetime_ne(DateTime *dt1, DateTime *dt2);
+extern bool datetime_lt(DateTime *dt1, DateTime *dt2);
+extern bool datetime_le(DateTime *dt1, DateTime *dt2);
+extern bool datetime_ge(DateTime *dt1, DateTime *dt2);
+extern bool datetime_gt(DateTime *dt1, DateTime *dt2);
+extern bool datetime_finite(DateTime *datetime);
+extern int     datetime_cmp(DateTime *dt1, DateTime *dt2);
+extern DateTime *datetime_smaller(DateTime *dt1, DateTime *dt2);
+extern DateTime *datetime_larger(DateTime *dt1, DateTime *dt2);
+
+extern TimeSpan *timespan_in(char *str);
+extern char *timespan_out(TimeSpan *span);
+extern bool timespan_eq(TimeSpan *span1, TimeSpan *span2);
+extern bool timespan_ne(TimeSpan *span1, TimeSpan *span2);
+extern bool timespan_lt(TimeSpan *span1, TimeSpan *span2);
+extern bool timespan_le(TimeSpan *span1, TimeSpan *span2);
+extern bool timespan_ge(TimeSpan *span1, TimeSpan *span2);
+extern bool timespan_gt(TimeSpan *span1, TimeSpan *span2);
+extern bool timespan_finite(TimeSpan *span);
+extern int     timespan_cmp(TimeSpan *span1, TimeSpan *span2);
+extern TimeSpan *timespan_smaller(TimeSpan *span1, TimeSpan *span2);
+extern TimeSpan *timespan_larger(TimeSpan *span1, TimeSpan *span2);
+
+extern text *datetime_text(DateTime *datetime);
+extern DateTime *text_datetime(text *str);
+extern text *timespan_text(TimeSpan *timespan);
+extern TimeSpan *text_timespan(text *str);
+extern DateTime *datetime_trunc(text *units, DateTime *datetime);
+extern TimeSpan *timespan_trunc(text *units, TimeSpan *timespan);
+extern float64 datetime_part(text *units, DateTime *datetime);
+extern float64 timespan_part(text *units, TimeSpan *timespan);
+extern text *datetime_zone(text *zone, DateTime *datetime);
+
+extern TimeSpan *timespan_um(TimeSpan *span);
+extern TimeSpan *timespan_pl(TimeSpan *span1, TimeSpan *span2);
+extern TimeSpan *timespan_mi(TimeSpan *span1, TimeSpan *span2);
+extern TimeSpan *timespan_div(TimeSpan *span1, float8 *arg2);
+
+extern TimeSpan *datetime_mi(DateTime *dt1, DateTime *dt2);
+extern DateTime *datetime_pl_span(DateTime *dt, TimeSpan *span);
+extern DateTime *datetime_mi_span(DateTime *dt, TimeSpan *span);
+extern TimeSpan *datetime_age(DateTime *dt1, DateTime *dt2);
+
+
+#endif
+
+
+extern void GetCurrentTime(struct tm * tm);
+extern void j2date(int jd, int *year, int *month, int *day);
+extern int     date2j(int year, int month, int day);
+
+extern int ParseDateTime(char *timestr, char *lowstr,
+                                                char **field, int *ftype,
+                                                int maxfields, int *numfields);
+extern int DecodeDateTime(char **field, int *ftype,
+                                                 int nf, int *dtype,
+                                                 struct tm * tm, double *fsec, int *tzp);
+
+extern int DecodeTimeOnly(char **field, int *ftype, int nf,
+                                                 int *dtype, struct tm * tm, double *fsec);
+
+extern int DecodeDateDelta(char **field, int *ftype,
+                                                  int nf, int *dtype,
+                                                  struct tm * tm, double *fsec);
+
+extern int EncodeDateOnly(struct tm * tm, int style, char *str);
+extern int EncodeTimeOnly(struct tm * tm, double fsec, int style, char *str);
+extern int EncodeDateTime(struct tm * tm, double fsec, int *tzp, char **tzn, int style, char *str);
+extern int EncodeTimeSpan(struct tm * tm, double fsec, int style, char *str);
+
+extern int DecodeDate(char *str, int fmask, int *tmask, struct tm * tm);
+extern int DecodeNumber(int flen, char *field,
+                                               int fmask, int *tmask,
+                                               struct tm * tm, double *fsec, int *is2digits);
+extern int DecodeNumberField(int len, char *str,
+                                                        int fmask, int *tmask,
+                                                        struct tm * tm, double *fsec, int *is2digits);
+extern int DecodeSpecial(int field, char *lowtoken, int *val);
+extern int DecodeTime(char *str, int fmask, int *tmask,
+                                         struct tm * tm, double *fsec);
+extern int DecodeTimezone(char *str, int *tzp);
+extern int DecodeUnits(int field, char *lowtoken, int *val);
+extern datetkn *datebsearch(char *key, datetkn *base, unsigned int nel);
+
+extern int j2day(int jd);
+
+
+#if 0
+
+
+static int EncodeSpecialTimestamp(Timestamp dt, char *str);
+static Timestamp dt2local(Timestamp dt, int timezone);
+static void dt2time(Timestamp dt, int *hour, int *min, double *sec);
+static int     timespan2tm(TimeSpan span, struct tm * tm, float8 *fsec);
+static int     tm2timespan(struct tm * tm, double fsec, TimeSpan *span);
+
+
+#endif
 
-typedef float8 TimeADT;
 
 #endif  /* DATETIME_H */
diff --git a/src/include/utils/dt.h b/src/include/utils/dt.h
deleted file mode 100644 (file)
index 739c3c2..0000000
+++ /dev/null
@@ -1,378 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * dt.h
- *       Definitions for the date/time and other date/time support code.
- *       The support code is shared with other date data types,
- *        including abstime, reltime, date, and time.
- *
- *
- * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- * $Id: dt.h,v 1.42 2000/01/26 05:58:37 momjian Exp $
- *
- *-------------------------------------------------------------------------
- */
-#ifndef DT_H
-#define DT_H
-
-#include <time.h>
-#include <math.h>
-#include <limits.h>
-
-/*
- * DateTime represents absolute time.
- * TimeSpan represents delta time. Keep track of months (and years)
- *     separately since the elapsed time spanned is unknown until instantiated
- *     relative to an absolute time.
- *
- * Note that Postgres uses "time interval" to mean a bounded interval,
- *     consisting of a beginning and ending time, not a time span - thomas 97/03/20
- */
-
-typedef double DateTime;
-
-typedef struct
-{
-       double          time;                   /* all time units other than months and
-                                                                * years */
-       int4            month;                  /* months and years, after time for
-                                                                * alignment */
-} TimeSpan;
-
-
-/* ----------------------------------------------------------------
- *                             time types + support macros
- *
- * String definitions for standard time quantities.
- *
- * These strings are the defaults used to form output time strings.
- * Other alternate forms are hardcoded into token tables in dt.c.
- * ----------------------------------------------------------------
- */
-
-#define DAGO                   "ago"
-#define DCURRENT               "current"
-#define EPOCH                  "epoch"
-#define INVALID                        "invalid"
-#define EARLY                  "-infinity"
-#define LATE                   "infinity"
-#define NOW                            "now"
-#define TODAY                  "today"
-#define TOMORROW               "tomorrow"
-#define YESTERDAY              "yesterday"
-#define ZULU                   "zulu"
-
-#define DMICROSEC              "usecond"
-#define DMILLISEC              "msecond"
-#define DSECOND                        "second"
-#define DMINUTE                        "minute"
-#define DHOUR                  "hour"
-#define DDAY                   "day"
-#define DWEEK                  "week"
-#define DMONTH                 "month"
-#define DQUARTER               "quarter"
-#define DYEAR                  "year"
-#define DDECADE                        "decade"
-#define DCENTURY               "century"
-#define DMILLENIUM             "millenium"
-#define DA_D                   "ad"
-#define DB_C                   "bc"
-#define DTIMEZONE              "timezone"
-
-/*
- * Fundamental time field definitions for parsing.
- *
- *     Meridian:  am, pm, or 24-hour style.
- *     Millenium: ad, bc
- */
-
-#define AM             0
-#define PM             1
-#define HR24   2
-
-#define AD             0
-#define BC             1
-
-/*
- * Fields for time decoding.
- * Can't have more of these than there are bits in an unsigned int
- *     since these are turned into bit masks during parsing and decoding.
- */
-
-#define RESERV 0
-#define MONTH  1
-#define YEAR   2
-#define DAY            3
-#define TIMES  4                               /* not used - thomas 1997-07-14 */
-#define TZ             5
-#define DTZ            6
-#define DTZMOD 7
-#define IGNORE 8
-#define AMPM   9
-#define HOUR   10
-#define MINUTE 11
-#define SECOND 12
-#define DOY            13
-#define DOW            14
-#define UNITS  15
-#define ADBC   16
-/* these are only for relative dates */
-#define AGO            17
-#define ABS_BEFORE             18
-#define ABS_AFTER              19
-
-/*
- * Token field definitions for time parsing and decoding.
- * These need to fit into the datetkn table type.
- * At the moment, that means keep them within [-127,127].
- * These are also used for bit masks in DecodeDateDelta()
- *     so actually restrict them to within [0,31] for now.
- * - thomas 97/06/19
- * Not all of these fields are used for masks in DecodeDateDelta
- *     so allow some larger than 31. - thomas 1997-11-17
- */
-
-#define DTK_NUMBER             0
-#define DTK_STRING             1
-
-#define DTK_DATE               2
-#define DTK_TIME               3
-#define DTK_TZ                 4
-#define DTK_AGO                        5
-
-#define DTK_SPECIAL            6
-#define DTK_INVALID            7
-#define DTK_CURRENT            8
-#define DTK_EARLY              9
-#define DTK_LATE               10
-#define DTK_EPOCH              11
-#define DTK_NOW                        12
-#define DTK_YESTERDAY  13
-#define DTK_TODAY              14
-#define DTK_TOMORROW   15
-#define DTK_ZULU               16
-
-#define DTK_DELTA              17
-#define DTK_SECOND             18
-#define DTK_MINUTE             19
-#define DTK_HOUR               20
-#define DTK_DAY                        21
-#define DTK_WEEK               22
-#define DTK_MONTH              23
-#define DTK_QUARTER            24
-#define DTK_YEAR               25
-#define DTK_DECADE             26
-#define DTK_CENTURY            27
-#define DTK_MILLENIUM  28
-#define DTK_MILLISEC   29
-#define DTK_MICROSEC   30
-
-#define DTK_DOW                        32
-#define DTK_DOY                        33
-#define DTK_TZ_HOUR            34
-#define DTK_TZ_MINUTE  35
-
-/*
- * Bit mask definitions for time parsing.
- */
-
-#define DTK_M(t)               (0x01 << (t))
-
-#define DTK_DATE_M             (DTK_M(YEAR) | DTK_M(MONTH) | DTK_M(DAY))
-#define DTK_TIME_M             (DTK_M(HOUR) | DTK_M(MINUTE) | DTK_M(SECOND))
-
-#define MAXDATELEN             47              /* maximum possible length of an input
-                                                                * date string */
-#define MAXDATEFIELDS  25              /* maximum possible number of fields in a
-                                                                * date string */
-#define TOKMAXLEN              10              /* only this many chars are stored in
-                                                                * datetktbl */
-
-/* keep this struct small; it gets used a lot */
-typedef struct
-{
-#if defined(_AIX)
-       char       *token;
-#else
-       char            token[TOKMAXLEN];
-#endif  /* _AIX */
-       char            type;
-       char            value;                  /* this may be unsigned, alas */
-} datetkn;
-
-#ifdef NAN
-#define DT_INVALID             (NAN)
-#else
-#define DT_INVALID             (DBL_MIN+DBL_MIN)
-#endif
-#ifdef HUGE_VAL
-#define DT_NOBEGIN             (-HUGE_VAL)
-#define DT_NOEND               (HUGE_VAL)
-#else
-#define DT_NOBEGIN             (-DBL_MAX)
-#define DT_NOEND               (DBL_MAX)
-#endif
-#define DT_CURRENT             (DBL_MIN)
-#define DT_EPOCH               (-DBL_MIN)
-
-#define DATETIME_INVALID(j)            {j = DT_INVALID;}
-#ifdef NAN
-#define DATETIME_IS_INVALID(j) (isnan(j))
-#else
-#define DATETIME_IS_INVALID(j) (j == DT_INVALID)
-#endif
-
-#define DATETIME_NOBEGIN(j)            {j = DT_NOBEGIN;}
-#define DATETIME_IS_NOBEGIN(j) (j == DT_NOBEGIN)
-
-#define DATETIME_NOEND(j)              {j = DT_NOEND;}
-#define DATETIME_IS_NOEND(j)   (j == DT_NOEND)
-
-#define DATETIME_CURRENT(j)            {j = DT_CURRENT;}
-#if defined(linux) && defined(__powerpc__)
-extern int     datetime_is_current(double j);
-
-#define DATETIME_IS_CURRENT(j) datetime_is_current(j)
-#else
-#define DATETIME_IS_CURRENT(j) (j == DT_CURRENT)
-#endif
-
-#define DATETIME_EPOCH(j)              {j = DT_EPOCH;}
-#if defined(linux) && defined(__powerpc__)
-extern int     datetime_is_epoch(double j);
-
-#define DATETIME_IS_EPOCH(j)   datetime_is_epoch(j)
-#else
-#define DATETIME_IS_EPOCH(j)   (j == DT_EPOCH)
-#endif
-
-#define DATETIME_IS_RELATIVE(j) (DATETIME_IS_CURRENT(j) || DATETIME_IS_EPOCH(j))
-#define DATETIME_NOT_FINITE(j) (DATETIME_IS_INVALID(j) \
-                                                               || DATETIME_IS_NOBEGIN(j) || DATETIME_IS_NOEND(j))
-#define DATETIME_IS_RESERVED(j) (DATETIME_IS_RELATIVE(j) || DATETIME_NOT_FINITE(j))
-
-#define TIMESPAN_INVALID(j)            {(j).time = DT_INVALID;}
-#ifdef NAN
-#define TIMESPAN_IS_INVALID(j) (isnan((j).time))
-#else
-#define TIMESPAN_IS_INVALID(j) ((j).time == DT_INVALID)
-#endif
-#define TIMESPAN_NOT_FINITE(j) TIMESPAN_IS_INVALID(j)
-
-#define TIME_PREC_INV 1000000.0
-#define JROUND(j) (rint(((double) (j))*TIME_PREC_INV)/TIME_PREC_INV)
-
-
-
-/*
- * Date/time validation
- * Include check for leap year.
- */
-
-extern int     day_tab[2][13];
-
-#define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
-
-/* Julian date support for date2j() and j2date()
- * Set the minimum year to one greater than the year of the first valid day
- *     to avoid having to check year and day both. - tgl 97/05/08
- */
-
-#define JULIAN_MINYEAR (-4713)
-#define JULIAN_MINMONTH (11)
-#define JULIAN_MINDAY (23)
-
-#define IS_VALID_JULIAN(y,m,d) ((y > JULIAN_MINYEAR) \
- || ((y == JULIAN_MINYEAR) && ((m > JULIAN_MINMONTH) \
-  || ((m == JULIAN_MINMONTH) && (d >= JULIAN_MINDAY)))))
-
-#define UTIME_MINYEAR (1901)
-#define UTIME_MINMONTH (12)
-#define UTIME_MINDAY (14)
-#define UTIME_MAXYEAR (2038)
-#define UTIME_MAXMONTH (01)
-#define UTIME_MAXDAY (18)
-
-#define IS_VALID_UTIME(y,m,d) (((y > UTIME_MINYEAR) \
- || ((y == UTIME_MINYEAR) && ((m > UTIME_MINMONTH) \
-  || ((m == UTIME_MINMONTH) && (d >= UTIME_MINDAY))))) \
- && ((y < UTIME_MAXYEAR) \
- || ((y == UTIME_MAXYEAR) && ((m < UTIME_MAXMONTH) \
-  || ((m == UTIME_MAXMONTH) && (d <= UTIME_MAXDAY))))))
-
-/*
- * dt.c prototypes
- */
-
-extern DateTime *datetime_in(char *str);
-extern char *datetime_out(DateTime *dt);
-extern bool datetime_eq(DateTime *dt1, DateTime *dt2);
-extern bool datetime_ne(DateTime *dt1, DateTime *dt2);
-extern bool datetime_lt(DateTime *dt1, DateTime *dt2);
-extern bool datetime_le(DateTime *dt1, DateTime *dt2);
-extern bool datetime_ge(DateTime *dt1, DateTime *dt2);
-extern bool datetime_gt(DateTime *dt1, DateTime *dt2);
-extern bool datetime_finite(DateTime *datetime);
-extern int     datetime_cmp(DateTime *dt1, DateTime *dt2);
-extern DateTime *datetime_smaller(DateTime *dt1, DateTime *dt2);
-extern DateTime *datetime_larger(DateTime *dt1, DateTime *dt2);
-
-extern TimeSpan *timespan_in(char *str);
-extern char *timespan_out(TimeSpan *span);
-extern bool timespan_eq(TimeSpan *span1, TimeSpan *span2);
-extern bool timespan_ne(TimeSpan *span1, TimeSpan *span2);
-extern bool timespan_lt(TimeSpan *span1, TimeSpan *span2);
-extern bool timespan_le(TimeSpan *span1, TimeSpan *span2);
-extern bool timespan_ge(TimeSpan *span1, TimeSpan *span2);
-extern bool timespan_gt(TimeSpan *span1, TimeSpan *span2);
-extern bool timespan_finite(TimeSpan *span);
-extern int     timespan_cmp(TimeSpan *span1, TimeSpan *span2);
-extern TimeSpan *timespan_smaller(TimeSpan *span1, TimeSpan *span2);
-extern TimeSpan *timespan_larger(TimeSpan *span1, TimeSpan *span2);
-
-extern text *datetime_text(DateTime *datetime);
-extern DateTime *text_datetime(text *str);
-extern text *timespan_text(TimeSpan *timespan);
-extern TimeSpan *text_timespan(text *str);
-extern DateTime *datetime_trunc(text *units, DateTime *datetime);
-extern TimeSpan *timespan_trunc(text *units, TimeSpan *timespan);
-extern float64 datetime_part(text *units, DateTime *datetime);
-extern float64 timespan_part(text *units, TimeSpan *timespan);
-extern text *datetime_zone(text *zone, DateTime *datetime);
-
-extern TimeSpan *timespan_um(TimeSpan *span);
-extern TimeSpan *timespan_pl(TimeSpan *span1, TimeSpan *span2);
-extern TimeSpan *timespan_mi(TimeSpan *span1, TimeSpan *span2);
-extern TimeSpan *timespan_div(TimeSpan *span1, float8 *arg2);
-
-extern TimeSpan *datetime_mi(DateTime *dt1, DateTime *dt2);
-extern DateTime *datetime_pl_span(DateTime *dt, TimeSpan *span);
-extern DateTime *datetime_mi_span(DateTime *dt, TimeSpan *span);
-extern TimeSpan *datetime_age(DateTime *dt1, DateTime *dt2);
-
-extern void GetCurrentTime(struct tm * tm);
-extern DateTime SetDateTime(DateTime datetime);
-extern int     tm2datetime(struct tm * tm, double fsec, int *tzp, DateTime *dt);
-extern int     datetime2tm(DateTime dt, int *tzp, struct tm * tm, double *fsec, char **tzn);
-
-extern void j2date(int jd, int *year, int *month, int *day);
-extern int     date2j(int year, int month, int day);
-
-extern int ParseDateTime(char *timestr, char *lowstr,
-                         char **field, int *ftype, int maxfields, int *numfields);
-extern int DecodeDateTime(char **field, int *ftype,
-                        int nf, int *dtype, struct tm * tm, double *fsec, int *tzp);
-
-extern int DecodeTimeOnly(char **field, int *ftype, int nf,
-                          int *dtype, struct tm * tm, double *fsec);
-
-extern int DecodeDateDelta(char **field, int *ftype,
-                               int nf, int *dtype, struct tm * tm, double *fsec);
-
-extern int     EncodeDateOnly(struct tm * tm, int style, char *str);
-extern int     EncodeTimeOnly(struct tm * tm, double fsec, int style, char *str);
-extern int     EncodeDateTime(struct tm * tm, double fsec, int *tzp, char **tzn, int style, char *str);
-extern int     EncodeTimeSpan(struct tm * tm, double fsec, int style, char *str);
-
-#endif  /* DT_H */
index 51c649fd9da8dd3edea6167b295b2a61f15ce479..39259afff248f3eccef3c61a24d5e220e4718d25 100644 (file)
@@ -2,7 +2,7 @@
 /* -----------------------------------------------------------------------
  * formatting.h
  *
- * $Id: formatting.h,v 1.2 2000/02/08 15:56:57 momjian Exp $
+ * $Id: formatting.h,v 1.3 2000/02/16 17:26:26 thomas Exp $
  *
  *
  *   Portions Copyright (c) 1999-2000, PostgreSQL, Inc
 #ifndef _FORMATTING_H_
 #define _FORMATTING_H_
 
-extern text    *datetime_to_char(DateTime *dt, text *fmt);
-extern text    *timestamp_to_char(time_t dt, text *fmt);
-extern DateTime *to_datetime(text *date_str, text *fmt);
-extern time_t  to_timestamp(text *date_str, text *fmt);
-extern DateADT  to_date(text *date_str, text *fmt);
-extern Numeric numeric_to_number(text *value, text *fmt);
-extern text    *numeric_to_char(Numeric value, text *fmt);
-extern text    *int4_to_char(int32 value, text *fmt);
-extern text    *int8_to_char(int64 *value, text *fmt);
-extern text    *float4_to_char(float32 value, text *fmt);
-extern text    *float8_to_char(float64 value, text *fmt);
+extern text *timestamp_to_char(Timestamp *dt, text *fmt);
+extern Timestamp *to_timestamp(text *date_str, text *fmt);
+extern DateADT to_date(text *date_str, text *fmt);
+extern Numeric numeric_to_number(text *value, text *fmt);
+extern text *numeric_to_char(Numeric value, text *fmt);
+extern text *int4_to_char(int32 value, text *fmt);
+extern text *int8_to_char(int64 *value, text *fmt);
+extern text *float4_to_char(float32 value, text *fmt);
+extern text *float8_to_char(float64 value, text *fmt);
 
 #endif
index 4da1c2834368addbc6d4ed0d6ef321d2d1ca16c7..09eea75ec644b6b5285d47e27456f5e3339a4a85 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: nabstime.h,v 1.22 2000/01/26 05:58:38 momjian Exp $
+ * $Id: nabstime.h,v 1.23 2000/02/16 17:26:26 thomas Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -15,7 +15,8 @@
 #define NABSTIME_H
 
 #include <time.h>
-#include "utils/dt.h"
+#include "utils/timestamp.h"
+#include "utils/datetime.h"
 
 
 /* ----------------------------------------------------------------
@@ -119,11 +120,51 @@ extern bool abstimele(AbsoluteTime t1, AbsoluteTime t2);
 extern bool abstimege(AbsoluteTime t1, AbsoluteTime t2);
 extern bool abstime_finite(AbsoluteTime time);
 
-extern AbsoluteTime datetime_abstime(DateTime *datetime);
-extern DateTime *abstime_datetime(AbsoluteTime abstime);
+extern AbsoluteTime timestamp_abstime(Timestamp *timestamp);
+extern Timestamp *abstime_timestamp(AbsoluteTime abstime);
 
 extern bool AbsoluteTimeIsBefore(AbsoluteTime time1, AbsoluteTime time2);
 
 extern void abstime2tm(AbsoluteTime time, int *tzp, struct tm * tm, char *tzn);
 
+extern RelativeTime reltimein(char *timestring);
+extern char *reltimeout(RelativeTime timevalue);
+extern TimeInterval tintervalin(char *intervalstr);
+extern char *tintervalout(TimeInterval interval);
+extern RelativeTime interval_reltime(Interval *interval);
+extern Interval *reltime_interval(RelativeTime reltime);
+extern TimeInterval mktinterval(AbsoluteTime t1, AbsoluteTime t2);
+extern AbsoluteTime timepl(AbsoluteTime t1, RelativeTime t2);
+extern AbsoluteTime timemi(AbsoluteTime t1, RelativeTime t2);
+
+/* extern RelativeTime abstimemi(AbsoluteTime t1, AbsoluteTime t2);  static*/
+extern int     intinterval(AbsoluteTime t, TimeInterval interval);
+extern RelativeTime tintervalrel(TimeInterval interval);
+extern AbsoluteTime timenow(void);
+extern bool reltimeeq(RelativeTime t1, RelativeTime t2);
+extern bool reltimene(RelativeTime t1, RelativeTime t2);
+extern bool reltimelt(RelativeTime t1, RelativeTime t2);
+extern bool reltimegt(RelativeTime t1, RelativeTime t2);
+extern bool reltimele(RelativeTime t1, RelativeTime t2);
+extern bool reltimege(RelativeTime t1, RelativeTime t2);
+extern bool tintervalsame(TimeInterval i1, TimeInterval i2);
+extern bool tintervaleq(TimeInterval i1, TimeInterval i2);
+extern bool tintervalne(TimeInterval i1, TimeInterval i2);
+extern bool tintervallt(TimeInterval i1, TimeInterval i2);
+extern bool tintervalgt(TimeInterval i1, TimeInterval i2);
+extern bool tintervalle(TimeInterval i1, TimeInterval i2);
+extern bool tintervalge(TimeInterval i1, TimeInterval i2);
+extern bool tintervalleneq(TimeInterval i, RelativeTime t);
+extern bool tintervallenne(TimeInterval i, RelativeTime t);
+extern bool tintervallenlt(TimeInterval i, RelativeTime t);
+extern bool tintervallengt(TimeInterval i, RelativeTime t);
+extern bool tintervallenle(TimeInterval i, RelativeTime t);
+extern bool tintervallenge(TimeInterval i, RelativeTime t);
+extern bool tintervalct(TimeInterval i1, TimeInterval i2);
+extern bool tintervalov(TimeInterval i1, TimeInterval i2);
+extern AbsoluteTime tintervalstart(TimeInterval i);
+extern AbsoluteTime tintervalend(TimeInterval i);
+extern int32 int4reltime(int32 timevalue);
+extern text *timeofday(void);
+
 #endif  /* NABSTIME_H */
diff --git a/src/include/utils/timestamp.h b/src/include/utils/timestamp.h
new file mode 100644 (file)
index 0000000..27a5288
--- /dev/null
@@ -0,0 +1,208 @@
+/*-------------------------------------------------------------------------
+ *
+ * timestamp.h
+ *       Definitions for the SQL92 "timestamp" and "interval" types.
+ *
+ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * $Id: timestamp.h,v 1.1 2000/02/16 17:26:26 thomas Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef TIMESTAMP_H
+#define TIMESTAMP_H
+
+#include <time.h>
+#include <math.h>
+#include <limits.h>
+
+/*
+ * Timestamp represents absolute time.
+ * Interval represents delta time. Keep track of months (and years)
+ *     separately since the elapsed time spanned is unknown until instantiated
+ *     relative to an absolute time.
+ *
+ * Note that Postgres uses "time interval" to mean a bounded interval,
+ *     consisting of a beginning and ending time, not a time span - thomas 97/03/20
+ */
+
+typedef double Timestamp;
+
+typedef struct
+{
+       double          time;                   /* all time units other than months and
+                                                                * years */
+       int4            month;                  /* months and years, after time for
+                                                                * alignment */
+} Interval;
+
+
+#ifdef NAN
+#define DT_INVALID             (NAN)
+#else
+#define DT_INVALID             (DBL_MIN+DBL_MIN)
+#endif
+#ifdef HUGE_VAL
+#define DT_NOBEGIN             (-HUGE_VAL)
+#define DT_NOEND               (HUGE_VAL)
+#else
+#define DT_NOBEGIN             (-DBL_MAX)
+#define DT_NOEND               (DBL_MAX)
+#endif
+#define DT_CURRENT             (DBL_MIN)
+#define DT_EPOCH               (-DBL_MIN)
+
+#define TIMESTAMP_INVALID(j)           {j = DT_INVALID;}
+#ifdef NAN
+#define TIMESTAMP_IS_INVALID(j)        (isnan(j))
+#else
+#define TIMESTAMP_IS_INVALID(j)        (j == DT_INVALID)
+#endif
+
+#define TIMESTAMP_NOBEGIN(j)           {j = DT_NOBEGIN;}
+#define TIMESTAMP_IS_NOBEGIN(j)        (j == DT_NOBEGIN)
+
+#define TIMESTAMP_NOEND(j)             {j = DT_NOEND;}
+#define TIMESTAMP_IS_NOEND(j)  (j == DT_NOEND)
+
+#define TIMESTAMP_CURRENT(j)           {j = DT_CURRENT;}
+#if defined(linux) && defined(__powerpc__)
+extern int     timestamp_is_current(double j);
+
+#define TIMESTAMP_IS_CURRENT(j)        timestamp_is_current(j)
+#else
+#define TIMESTAMP_IS_CURRENT(j)        (j == DT_CURRENT)
+#endif
+
+#define TIMESTAMP_EPOCH(j)             {j = DT_EPOCH;}
+#if defined(linux) && defined(__powerpc__)
+extern int     timestamp_is_epoch(double j);
+
+#define TIMESTAMP_IS_EPOCH(j)  timestamp_is_epoch(j)
+#else
+#define TIMESTAMP_IS_EPOCH(j)  (j == DT_EPOCH)
+#endif
+
+#define TIMESTAMP_IS_RELATIVE(j) (TIMESTAMP_IS_CURRENT(j) || TIMESTAMP_IS_EPOCH(j))
+#define TIMESTAMP_NOT_FINITE(j)        (TIMESTAMP_IS_INVALID(j) \
+                                                               || TIMESTAMP_IS_NOBEGIN(j) || TIMESTAMP_IS_NOEND(j))
+#define TIMESTAMP_IS_RESERVED(j) (TIMESTAMP_IS_RELATIVE(j) || TIMESTAMP_NOT_FINITE(j))
+
+#define INTERVAL_INVALID(j)            {(j).time = DT_INVALID;}
+#ifdef NAN
+#define INTERVAL_IS_INVALID(j) (isnan((j).time))
+#else
+#define INTERVAL_IS_INVALID(j) ((j).time == DT_INVALID)
+#endif
+#define INTERVAL_NOT_FINITE(j) INTERVAL_IS_INVALID(j)
+
+#define TIME_PREC_INV 1000000.0
+#define JROUND(j) (rint(((double) (j))*TIME_PREC_INV)/TIME_PREC_INV)
+
+
+#if 0
+
+
+/*
+ * Date/time validation
+ * Include check for leap year.
+ */
+
+extern int     day_tab[2][13];
+
+#define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
+
+/* Julian date support for date2j() and j2date()
+ * Set the minimum year to one greater than the year of the first valid day
+ *     to avoid having to check year and day both. - tgl 97/05/08
+ */
+
+#define JULIAN_MINYEAR (-4713)
+#define JULIAN_MINMONTH (11)
+#define JULIAN_MINDAY (23)
+
+#define IS_VALID_JULIAN(y,m,d) ((y > JULIAN_MINYEAR) \
+ || ((y == JULIAN_MINYEAR) && ((m > JULIAN_MINMONTH) \
+  || ((m == JULIAN_MINMONTH) && (d >= JULIAN_MINDAY)))))
+
+#define UTIME_MINYEAR (1901)
+#define UTIME_MINMONTH (12)
+#define UTIME_MINDAY (14)
+#define UTIME_MAXYEAR (2038)
+#define UTIME_MAXMONTH (01)
+#define UTIME_MAXDAY (18)
+
+#define IS_VALID_UTIME(y,m,d) (((y > UTIME_MINYEAR) \
+ || ((y == UTIME_MINYEAR) && ((m > UTIME_MINMONTH) \
+  || ((m == UTIME_MINMONTH) && (d >= UTIME_MINDAY))))) \
+ && ((y < UTIME_MAXYEAR) \
+ || ((y == UTIME_MAXYEAR) && ((m < UTIME_MAXMONTH) \
+  || ((m == UTIME_MAXMONTH) && (d <= UTIME_MAXDAY))))))
+
+
+#endif
+
+
+/*
+ * timestamp.c prototypes
+ */
+
+extern Timestamp *timestamp_in(char *str);
+extern char *timestamp_out(Timestamp *dt);
+extern bool timestamp_eq(Timestamp *dt1, Timestamp *dt2);
+extern bool timestamp_ne(Timestamp *dt1, Timestamp *dt2);
+extern bool timestamp_lt(Timestamp *dt1, Timestamp *dt2);
+extern bool timestamp_le(Timestamp *dt1, Timestamp *dt2);
+extern bool timestamp_ge(Timestamp *dt1, Timestamp *dt2);
+extern bool timestamp_gt(Timestamp *dt1, Timestamp *dt2);
+extern bool timestamp_finite(Timestamp *timestamp);
+extern int     timestamp_cmp(Timestamp *dt1, Timestamp *dt2);
+extern Timestamp *timestamp_smaller(Timestamp *dt1, Timestamp *dt2);
+extern Timestamp *timestamp_larger(Timestamp *dt1, Timestamp *dt2);
+
+extern Interval *interval_in(char *str);
+extern char *interval_out(Interval *span);
+extern bool interval_eq(Interval *span1, Interval *span2);
+extern bool interval_ne(Interval *span1, Interval *span2);
+extern bool interval_lt(Interval *span1, Interval *span2);
+extern bool interval_le(Interval *span1, Interval *span2);
+extern bool interval_ge(Interval *span1, Interval *span2);
+extern bool interval_gt(Interval *span1, Interval *span2);
+extern bool interval_finite(Interval *span);
+extern int     interval_cmp(Interval *span1, Interval *span2);
+extern Interval *interval_smaller(Interval *span1, Interval *span2);
+extern Interval *interval_larger(Interval *span1, Interval *span2);
+
+extern text *timestamp_text(Timestamp *timestamp);
+extern Timestamp *text_timestamp(text *str);
+extern text *interval_text(Interval *interval);
+extern Interval *text_interval(text *str);
+extern Timestamp *timestamp_trunc(text *units, Timestamp *timestamp);
+extern Interval *interval_trunc(text *units, Interval *interval);
+extern float64 timestamp_part(text *units, Timestamp *timestamp);
+extern float64 interval_part(text *units, Interval *interval);
+extern text *timestamp_zone(text *zone, Timestamp *timestamp);
+
+extern Interval *interval_um(Interval *span);
+extern Interval *interval_pl(Interval *span1, Interval *span2);
+extern Interval *interval_mi(Interval *span1, Interval *span2);
+extern Interval *interval_div(Interval *span1, float8 *arg2);
+
+extern Interval *timestamp_mi(Timestamp *dt1, Timestamp *dt2);
+extern Timestamp *timestamp_pl_span(Timestamp *dt, Interval *span);
+extern Timestamp *timestamp_mi_span(Timestamp *dt, Interval *span);
+extern Interval *timestamp_age(Timestamp *dt1, Timestamp *dt2);
+
+extern int     tm2timestamp(struct tm * tm, double fsec, int *tzp, Timestamp *dt);
+extern int     timestamp2tm(Timestamp dt, int *tzp, struct tm * tm, double *fsec, char **tzn);
+
+extern Timestamp SetTimestamp(Timestamp timestamp);
+extern Timestamp dt2local(Timestamp dt, int timezone);
+extern void dt2time(Timestamp dt, int *hour, int *min, double *sec);
+extern int EncodeSpecialTimestamp(Timestamp dt, char *str);
+extern int interval2tm(Interval span, struct tm * tm, float8 *fsec);
+extern int tm2interval(struct tm * tm, double fsec, Interval *span);
+extern Timestamp *now(void);
+
+#endif  /* TIMESTAMP_H */