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 */