diff --git a/src/backend/utils/adt/dt.c b/src/backend/utils/adt/dt.c
index 542246a52b9d9ac88d9a9c03326b93e289a7a741..79e83266563f57f13e995fabf63232253d5a83a2 100644
--- a/src/backend/utils/adt/dt.c
+++ b/src/backend/utils/adt/dt.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *    $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/dt.c,v 1.24 1997/06/03 06:32:56 vadim Exp $
+ *    $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/dt.c,v 1.25 1997/06/20 17:12:54 thomas Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -48,7 +48,23 @@ char *days[] = {"Sunday", "Monday", "Tuesday", "Wednesday",
  * Macro to replace modf(), which is broken on some platforms.
  */
 #define TMODULO(t,q,u) {q = ((t < 0)? ceil(t / u): floor(t / u)); \
-                      if (q != 0) t -= rint(q * u);}
+			if (q != 0) t -= rint(q * u);}
+
+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))))))
 
 
 /***************************************************************************** 
@@ -79,8 +95,7 @@ datetime_in(char *str)
       || (DecodeDateTime( field, ftype, nf, &dtype, tm, &fsec, &tz) != 0))
 	elog(WARN,"Bad datetime external representation %s",str);
 
-    if (!PointerIsValid(result = PALLOCTYPE(DateTime)))
-	elog(WARN,"Memory allocation failed, can't input datetime '%s'",str);
+    result = PALLOCTYPE(DateTime);
 
     switch (dtype) {
     case DTK_DATE:
@@ -146,8 +161,7 @@ datetime_out(DateTime *dt)
 	EncodeSpecialDateTime(DT_INVALID, buf);
     };
 
-    if (!PointerIsValid(result = PALLOC(strlen(buf)+1)))
-	elog(WARN,"Memory allocation failed, can't output datetime",NULL);
+    result = PALLOC(strlen(buf)+1);
 
     strcpy( result, buf);
 
@@ -189,8 +203,7 @@ timespan_in(char *str)
       || (DecodeDateDelta( field, ftype, nf, &dtype, tm, &fsec) != 0))
 	elog(WARN,"Bad timespan external representation '%s'",str);
 
-    if (!PointerIsValid(span = PALLOCTYPE(TimeSpan)))
-	elog(WARN,"Memory allocation failed, can't input timespan '%s'",str);
+    span = PALLOCTYPE(TimeSpan);
 
     switch (dtype) {
     case DTK_DELTA:
@@ -230,8 +243,7 @@ timespan_out(TimeSpan *span)
     if (EncodeTimeSpan(tm, fsec, DateStyle, buf) != 0)
 	  elog(WARN,"Unable to format timespan",NULL);
 
-    if (!PointerIsValid(result = PALLOC(strlen(buf)+1)))
-	elog(WARN,"Memory allocation failed, can't output timespan",NULL);
+    result = PALLOC(strlen(buf)+1);
 
     strcpy( result, buf);
     return( result);
@@ -267,8 +279,6 @@ timespan_finite(TimeSpan *timespan)
  *  Relational operators for datetime.
  *---------------------------------------------------------*/
 
-void GetEpochTime( struct tm *tm);
-
 void
 GetEpochTime( struct tm *tm)
 {
@@ -556,7 +566,8 @@ timespan_ge(TimeSpan *timespan1, TimeSpan *timespan2)
  *			actual value.
  *---------------------------------------------------------*/
 
-DateTime *datetime_smaller(DateTime *datetime1, DateTime *datetime2)
+DateTime *
+datetime_smaller(DateTime *datetime1, DateTime *datetime2)
 {
     DateTime *result;
 
@@ -568,8 +579,7 @@ DateTime *datetime_smaller(DateTime *datetime1, DateTime *datetime2)
     dt1 = *datetime1;
     dt2 = *datetime2;
 
-    if (!PointerIsValid(result = PALLOCTYPE(DateTime)))
-	elog(WARN,"Memory allocation failed, can't find smaller date",NULL);
+    result = PALLOCTYPE(DateTime);
 
     if (DATETIME_IS_RELATIVE(dt1)) dt1 = SetDateTime(dt1);
     if (DATETIME_IS_RELATIVE(dt2)) dt2 = SetDateTime(dt2);
@@ -585,7 +595,8 @@ DateTime *datetime_smaller(DateTime *datetime1, DateTime *datetime2)
     return(result);
 } /* datetime_smaller() */
 
-DateTime *datetime_larger(DateTime *datetime1, DateTime *datetime2)
+DateTime *
+datetime_larger(DateTime *datetime1, DateTime *datetime2)
 {
     DateTime *result;
 
@@ -597,8 +608,7 @@ DateTime *datetime_larger(DateTime *datetime1, DateTime *datetime2)
     dt1 = *datetime1;
     dt2 = *datetime2;
 
-    if (!PointerIsValid(result = PALLOCTYPE(DateTime)))
-	elog(WARN,"Memory allocation failed, can't find larger date",NULL);
+    result = PALLOCTYPE(DateTime);
 
     if (DATETIME_IS_RELATIVE(dt1)) dt1 = SetDateTime(dt1);
     if (DATETIME_IS_RELATIVE(dt2)) dt2 = SetDateTime(dt2);
@@ -615,7 +625,8 @@ DateTime *datetime_larger(DateTime *datetime1, DateTime *datetime2)
 } /* datetime_larger() */
 
 
-TimeSpan *datetime_sub(DateTime *datetime1, DateTime *datetime2)
+TimeSpan *
+datetime_sub(DateTime *datetime1, DateTime *datetime2)
 {
     TimeSpan *result;
 
@@ -627,8 +638,7 @@ TimeSpan *datetime_sub(DateTime *datetime1, DateTime *datetime2)
     dt1 = *datetime1;
     dt2 = *datetime2;
 
-    if (!PointerIsValid(result = PALLOCTYPE(TimeSpan)))
-	elog(WARN,"Memory allocation failed, can't subtract dates",NULL);
+    result = PALLOCTYPE(TimeSpan);
 
     if (DATETIME_IS_RELATIVE(dt1)) dt1 = SetDateTime(dt1);
     if (DATETIME_IS_RELATIVE(dt2)) dt2 = SetDateTime(dt2);
@@ -654,15 +664,18 @@ TimeSpan *datetime_sub(DateTime *datetime1, DateTime *datetime2)
  * Then, if the next month has fewer days, set the day of month
  *  to the last day of month.
  */
-DateTime *datetime_add_span(DateTime *datetime, TimeSpan *span)
+DateTime *
+datetime_add_span(DateTime *datetime, TimeSpan *span)
 {
     DateTime *result;
+    DateTime dt;
+    int tz;
+    char *tzn;
 
     if ((!PointerIsValid(datetime)) || (!PointerIsValid(span)))
 	return NULL;
 
-    if (!PointerIsValid(result = PALLOCTYPE(DateTime)))
-	elog(WARN,"Memory allocation failed, can't add dates",NULL);
+    result = PALLOCTYPE(DateTime);
 
 #ifdef DATEDEBUG
 printf( "datetime_add_span- add %f to %d %f\n", *datetime, span->month, span->time);
@@ -675,13 +688,19 @@ printf( "datetime_add_span- add %f to %d %f\n", *datetime, span->month, span->ti
 	DATETIME_INVALID(*result);
 
     } else {
-	*result = (DATETIME_IS_RELATIVE(*datetime)? SetDateTime(*datetime): *datetime);
+	dt = (DATETIME_IS_RELATIVE(*datetime)? SetDateTime(*datetime): *datetime);
+
+#ifdef ROUND_ALL
+	dt = JROUND(dt + span->time);
+#else
+	dt = span->time;
+#endif
 
 	if (span->month != 0) {
 	    struct tm tt, *tm = &tt;
 	    double fsec;
 
-	    if (datetime2tm( *result, NULL, tm, &fsec, NULL) == 0) {
+	    if (datetime2tm( dt, &tz, tm, &fsec, &tzn) == 0) {
 #ifdef DATEDEBUG
 printf( "datetime_add_span- date was %d.%02d.%02d\n", tm->tm_year, tm->tm_mon, tm->tm_mday);
 #endif
@@ -706,26 +725,22 @@ printf( "datetime_add_span- date was %d.%02d.%02d\n", tm->tm_year, tm->tm_mon, t
 #ifdef DATEDEBUG
 printf( "datetime_add_span- date becomes %d.%02d.%02d\n", tm->tm_year, tm->tm_mon, tm->tm_mday);
 #endif
-		if (tm2datetime( tm, fsec, NULL, result) != 0)
+		if (tm2datetime( tm, fsec, &tz, &dt) != 0)
 		    elog(WARN,"Unable to add datetime and timespan",NULL);
 
-
 	    } else {
 		DATETIME_INVALID(*result);
 	    };
 	};
 
-#ifdef ROUND_ALL
-	*result = JROUND(*result + span->time);
-#else
-	*result += span->time;
-#endif
+	*result = dt;
     };
 
     return(result);
 } /* datetime_add_span() */
 
-DateTime *datetime_sub_span(DateTime *datetime, TimeSpan *span)
+DateTime *
+datetime_sub_span(DateTime *datetime, TimeSpan *span)
 {
     DateTime *result;
     TimeSpan tspan;
@@ -742,15 +757,15 @@ DateTime *datetime_sub_span(DateTime *datetime, TimeSpan *span)
 } /* datetime_sub_span() */
 
 
-TimeSpan *timespan_um(TimeSpan *timespan)
+TimeSpan *
+timespan_um(TimeSpan *timespan)
 {
     TimeSpan *result;
 
     if (!PointerIsValid(timespan))
 	return NULL;
 
-    if (!PointerIsValid(result = PALLOCTYPE(TimeSpan)))
-	elog(WARN,"Memory allocation failed, can't subtract dates",NULL);
+    result = PALLOCTYPE(TimeSpan);
 
     result->time = -(timespan->time);
     result->month = -(timespan->month);
@@ -759,7 +774,8 @@ TimeSpan *timespan_um(TimeSpan *timespan)
 } /* timespan_um() */
 
 
-TimeSpan *timespan_smaller(TimeSpan *timespan1, TimeSpan *timespan2)
+TimeSpan *
+timespan_smaller(TimeSpan *timespan1, TimeSpan *timespan2)
 {
     TimeSpan *result;
 
@@ -768,8 +784,7 @@ TimeSpan *timespan_smaller(TimeSpan *timespan1, TimeSpan *timespan2)
     if (!PointerIsValid(timespan1) || !PointerIsValid(timespan2))
 	return NULL;
 
-    if (!PointerIsValid(result = PALLOCTYPE(TimeSpan)))
-	elog(WARN,"Memory allocation failed, can't find smaller timespan",NULL);
+    result = PALLOCTYPE(TimeSpan);
 
     if (TIMESPAN_IS_INVALID(*timespan1)) {
 	result->time = timespan2->time;
@@ -803,7 +818,8 @@ printf( "timespan_smaller- months %d %d times %f %f spans %f %f\n",
     return(result);
 } /* timespan_smaller() */
 
-TimeSpan *timespan_larger(TimeSpan *timespan1, TimeSpan *timespan2)
+TimeSpan *
+timespan_larger(TimeSpan *timespan1, TimeSpan *timespan2)
 {
     TimeSpan *result;
 
@@ -812,8 +828,7 @@ TimeSpan *timespan_larger(TimeSpan *timespan1, TimeSpan *timespan2)
     if (!PointerIsValid(timespan1) || !PointerIsValid(timespan2))
 	return NULL;
 
-    if (!PointerIsValid(result = PALLOCTYPE(TimeSpan)))
-	elog(WARN,"Memory allocation failed, can't find larger timespan",NULL);
+    result = PALLOCTYPE(TimeSpan);
 
     if (TIMESPAN_IS_INVALID(*timespan1)) {
 	result->time = timespan2->time;
@@ -848,15 +863,15 @@ printf( "timespan_larger- months %d %d times %f %f spans %f %f\n",
 } /* timespan_larger() */
 
 
-TimeSpan *timespan_add(TimeSpan *span1, TimeSpan *span2)
+TimeSpan *
+timespan_add(TimeSpan *span1, TimeSpan *span2)
 {
     TimeSpan *result;
 
     if ((!PointerIsValid(span1)) || (!PointerIsValid(span2)))
 	return NULL;
 
-    if (!PointerIsValid(result = PALLOCTYPE(TimeSpan)))
-	elog(WARN,"Memory allocation failed, can't add timespans",NULL);
+    result = PALLOCTYPE(TimeSpan);
 
     result->month = (span1->month + span2->month);
     result->time = JROUND(span1->time + span2->time);
@@ -864,15 +879,15 @@ TimeSpan *timespan_add(TimeSpan *span1, TimeSpan *span2)
     return(result);
 } /* timespan_add() */
 
-TimeSpan *timespan_sub(TimeSpan *span1, TimeSpan *span2)
+TimeSpan *
+timespan_sub(TimeSpan *span1, TimeSpan *span2)
 {
     TimeSpan *result;
 
     if ((!PointerIsValid(span1)) || (!PointerIsValid(span2)))
 	return NULL;
 
-    if (!PointerIsValid(result = PALLOCTYPE(TimeSpan)))
-	elog(WARN,"Memory allocation failed, can't subtract timespans",NULL);
+    result = PALLOCTYPE(TimeSpan);
 
     result->month = (span1->month - span2->month);
     result->time = JROUND(span1->time - span2->time);
@@ -906,8 +921,7 @@ datetime_text(DateTime *datetime)
 
     len = (strlen(str)+VARHDRSZ);
 
-    if (!PointerIsValid(result = PALLOC(len)))
-	elog(WARN,"Memory allocation failed, can't convert datetime to text",NULL);
+    result = PALLOC(len);
 
     VARSIZE(result) = len;
     memmove(VARDATA(result), str, (len-VARHDRSZ));
@@ -964,8 +978,7 @@ timespan_text(TimeSpan *timespan)
 
     len = (strlen(str)+VARHDRSZ);
 
-    if (!PointerIsValid(result = PALLOC(len)))
-	elog(WARN,"Memory allocation failed, can't convert timespan to text",NULL);
+    result = PALLOC(len);
 
     VARSIZE(result) = len;
     memmove(VARDATA(result), str, (len-VARHDRSZ));
@@ -1022,8 +1035,7 @@ datetime_part(text *units, DateTime *datetime)
     if ((!PointerIsValid(units)) || (!PointerIsValid(datetime)))
 	return NULL;
 
-    if (!PointerIsValid(result = PALLOCTYPE(float64data)))
-	elog(WARN,"Memory allocation failed, can't get date part",NULL);
+    result = PALLOCTYPE(float64data);
 
     up = VARDATA(units);
     lp = lowunits;
@@ -1031,6 +1043,9 @@ datetime_part(text *units, DateTime *datetime)
     *lp = '\0';
 
     type = DecodeUnits( 0, lowunits, &val);
+    if (type == IGNORE) {
+	type = DecodeSpecial( 0, lowunits, &val);
+    };
 
 #ifdef DATEDEBUG
 if (type == IGNORE) strcpy(lowunits, "(unknown)");
@@ -1039,15 +1054,15 @@ printf( "datetime_part- units %s type=%d value=%d\n", lowunits, type, val);
 
     if (DATETIME_NOT_FINITE(*datetime)) {
 #if FALSE
+/* should return null but Postgres doesn't like that currently. - tgl 97/06/12 */
 	elog(WARN,"Datetime is not finite",NULL);
 #endif
 	*result = 0;
 
-    } else if (type == UNITS) {
-
+    } else {
 	dt = (DATETIME_IS_RELATIVE(*datetime)? SetDateTime(*datetime): *datetime); 
 
-	if (datetime2tm( dt, &tz, tm, &fsec, &tzn) == 0) {
+	if ((type == UNITS) && (datetime2tm( dt, &tz, tm, &fsec, &tzn) == 0)) {
 	    switch (val) {
 	    case DTK_TZ:
 		*result = tz;
@@ -1102,19 +1117,18 @@ printf( "datetime_part- units %s type=%d value=%d\n", lowunits, type, val);
 		break;
 
 	    default:
-		elog(WARN,"Datetime units %s not supported",units);
+		elog(WARN,"Datetime units %s not supported",lowunits);
 		*result = 0;
 	    };
 
+	} else if ((type == RESERV) && (val == DTK_EPOCH)) {
+	    DATETIME_EPOCH(*result);
+	    *result = dt - SetDateTime(*result);
+
 	} else {
-	    elog(NOTICE,"Datetime out of range",NULL);
+	    elog(WARN,"Datetime units %s not recognized",lowunits);
 	    *result = 0;
 	};
-
-
-    } else {
-	elog(WARN,"Datetime units %s not recognized",units);
-	*result = 0;
     };
 
     return(result);
@@ -1138,8 +1152,7 @@ timespan_part(text *units, TimeSpan *timespan)
     if ((!PointerIsValid(units)) || (!PointerIsValid(timespan)))
 	return NULL;
 
-    if (!PointerIsValid(result = PALLOCTYPE(float64data)))
-	elog(WARN,"Memory allocation failed, can't get date part",NULL);
+    result = PALLOCTYPE(float64data);
 
     up = VARDATA(units);
     lp = lowunits;
@@ -1147,6 +1160,9 @@ timespan_part(text *units, TimeSpan *timespan)
     *lp = '\0';
 
     type = DecodeUnits( 0, lowunits, &val);
+    if (type == IGNORE) {
+	type = DecodeSpecial( 0, lowunits, &val);
+    };
 
 #ifdef DATEDEBUG
 if (type == IGNORE) strcpy(lowunits, "(unknown)");
@@ -1221,6 +1237,12 @@ printf( "timespan_part- units %s type=%d value=%d\n", lowunits, type, val);
 	    *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(WARN,"Timespan units %s not recognized",units);
@@ -1284,7 +1306,7 @@ static datetkn datetktbl[] = {
 {	"dec",		MONTH,	12},
 {	"december",	MONTH,	12},
 {	"dnt",		TZ,	6},		/* Dansk Normal Tid */
-{	"dst",		IGNORE,	0},
+{	"dst",		DTZMOD,	6},
 {	"east",		TZ,	NEG(60)},	/* East Australian Std Time */
 {	"edt",		DTZ,	NEG(24)},	/* Eastern Daylight Time */
 {	"eet",		TZ,	12},		/* East. Europe, USSR Zone 1 */
@@ -1491,20 +1513,6 @@ datetkn *deltacache[MAXDATEFIELDS] = {NULL};
  *  to avoid having to check year and day both. - tgl 97/05/08
  */
 
-#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))))))
-
 #define JULIAN_MINYEAR (-4713)
 #define JULIAN_MINMONTH (11)
 #define JULIAN_MINDAY (23)
@@ -1522,7 +1530,8 @@ date2j(int y, int m, int d)
      - (3*((y+4900+m12)/100))/4 + d - 32075);
 } /* date2j() */
 
-void j2date( int jd, int *year, int *month, int *day)
+void
+j2date( int jd, int *year, int *month, int *day)
 {
     int j, y, m, d;
 
@@ -1545,7 +1554,8 @@ void j2date( int jd, int *year, int *month, int *day)
     return;
 } /* j2date() */
 
-int j2day( int date)
+int
+j2day( int date)
 {
     int day;
 
@@ -1766,19 +1776,22 @@ printf( "tm2timespan- %d %f = %04d-%02d-%02d %02d:%02d:%02d %.2f\n", span->month
 } /* tm2timespan() */
 
 
-DateTime dt2local(DateTime dt, int tz)
+DateTime
+dt2local(DateTime dt, int tz)
 {
     dt -= tz;
     dt = JROUND(dt);
     return(dt);
 } /* dt2local() */
 
-double time2t(const int hour, const int min, const double sec)
+double
+time2t(const int hour, const int min, const double sec)
 {
     return((((hour*60)+min)*60)+sec);
 } /* time2t() */
 
-void dt2time(DateTime jd, int *hour, int *min, double *sec)
+void
+dt2time(DateTime jd, int *hour, int *min, double *sec)
 {
     double time;
 
@@ -1940,7 +1953,7 @@ DecodeDateTime( char *field[], int ftype[], int nf,
     tm->tm_sec = 0;
     *fsec = 0;
     tm->tm_isdst = -1;	/* don't know daylight savings time status apriori */
-    if (tzp != NULL) *tzp = CTimeZone;
+    if (tzp != NULL) *tzp = 0;
 
     for (i = 0; i < nf; i++) {
 #ifdef DATEDEBUG
@@ -1995,6 +2008,7 @@ printf( "DecodeDateTime- RESERV field %s value is %d\n", field[i], val);
 		    tmask = (DTK_DATE_M | DTK_TIME_M | DTK_M(TZ));
 		    *dtype = DTK_DATE;
 		    GetCurrentTime(tm);
+		    if (tzp != NULL) *tzp = CTimeZone;
 		    break;
 
 		case DTK_YESTERDAY:
@@ -2050,7 +2064,17 @@ printf( "DecodeDateTime- month field %s value is %d\n", field[i], val);
 		tm->tm_mon = val;
 		break;
 
+	    /* daylight savings time modifier (solves "MET DST" syntax) */
+	    case DTZMOD:
+		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;
@@ -2628,7 +2652,7 @@ DecodeSpecial(int field, char *lowtoken, int *val)
 	*val = 0;
     } else {
 	type = tp->type;
-	if ((type == TZ) || (type == DTZ)) {
+	if ((type == TZ) || (type == DTZ) || (type == DTZMOD)) {
 	    *val = FROMVAL(tp);
 	} else {
 	    *val = tp->value;