diff --git a/src/backend/utils/adt/date.c b/src/backend/utils/adt/date.c
index 2c261198b45c998ebae5ed4411ed42ebd8be80bd..ab8403cc3183b38b162120f99a8105d767ec32f1 100644
--- a/src/backend/utils/adt/date.c
+++ b/src/backend/utils/adt/date.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/date.c,v 1.65 2002/03/09 17:35:35 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/date.c,v 1.66 2002/04/21 19:48:12 thomas Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -28,6 +28,10 @@
 #include "utils/timestamp.h"
 
 
+int time2tm(TimeADT time, struct tm * tm, fsec_t *fsec);
+int timetz2tm(TimeTzADT *time, struct tm * tm, fsec_t *fsec, int *tzp);
+int tm2time(struct tm * tm, fsec_t fsec, TimeADT *result);
+int tm2timetz(struct tm * tm, fsec_t fsec, int tz, TimeTzADT *result);
 static void AdjustTimeForTypmod(TimeADT *time, int32 typmod);
 
 /*****************************************************************************
@@ -43,7 +47,7 @@ date_in(PG_FUNCTION_ARGS)
 {
 	char	   *str = PG_GETARG_CSTRING(0);
 	DateADT		date;
-	double		fsec;
+	fsec_t		fsec;
 	struct tm	tt,
 			   *tm = &tt;
 	int			tzp;
@@ -221,6 +225,60 @@ date_mii(PG_FUNCTION_ARGS)
 	PG_RETURN_DATEADT(dateVal - days);
 }
 
+#if NOT_USED
+/* date_pl_interval() and date_mi_interval() are probably
+ * better implmented by converting the input date
+ * to timestamp without time zone. So that is what we do
+ * in pg_proc.h - thomas 2002-03-11
+ */
+
+/* Add an interval to a date, giving a new date.
+ * Must handle both positive and negative intervals.
+ */
+Datum
+date_pl_interval(PG_FUNCTION_ARGS)
+{
+	DateADT		dateVal = PG_GETARG_DATEADT(0);
+	Interval   *span = PG_GETARG_INTERVAL_P(1);
+	struct tm	tt,
+			   *tm = &tt;
+
+	if (span->month != 0)
+	{
+		j2date((dateVal + date2j(2000, 1, 1)), &(tm->tm_year), &(tm->tm_mon), &(tm->tm_mday));
+		tm->tm_mon += span->month;
+		dateVal = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - date2j(2000, 1, 1);
+	}
+	if (span->time != 0)
+		dateVal += (span->time / 86400e0);
+
+	PG_RETURN_DATEADT(dateVal);
+}
+
+/* Subtract an interval from a date, giving a new date.
+ * Must handle both positive and negative intervals.
+ */
+Datum
+date_mi_interval(PG_FUNCTION_ARGS)
+{
+	DateADT		dateVal = PG_GETARG_DATEADT(0);
+	Interval   *span = PG_GETARG_INTERVAL_P(1);
+	struct tm	tt,
+			   *tm = &tt;
+
+	if (span->month != 0)
+	{
+		j2date((dateVal + date2j(2000, 1, 1)), &(tm->tm_year), &(tm->tm_mon), &(tm->tm_mday));
+		tm->tm_mon -= span->month;
+		dateVal = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - date2j(2000, 1, 1);
+	}
+	if (span->time != 0)
+		dateVal -= (span->time / 86400e0);
+
+	PG_RETURN_DATEADT(dateVal);
+}
+#endif
+
 /* date_timestamp()
  * Convert date to timestamp data type.
  */
@@ -230,8 +288,13 @@ date_timestamp(PG_FUNCTION_ARGS)
 	DateADT		dateVal = PG_GETARG_DATEADT(0);
 	Timestamp	result;
 
+#ifdef HAVE_INT64_TIMESTAMP
+	/* date is days since 2000, timestamp is microseconds since same... */
+	result = dateVal * INT64CONST(86400000000);
+#else
 	/* date is days since 2000, timestamp is seconds since same... */
 	result = dateVal * 86400.0;
+#endif
 
 	PG_RETURN_TIMESTAMP(result);
 }
@@ -245,17 +308,23 @@ timestamp_date(PG_FUNCTION_ARGS)
 {
 	Timestamp	timestamp = PG_GETARG_TIMESTAMP(0);
 	DateADT		result;
+#if 0
 	struct tm	tt,
 			   *tm = &tt;
-	double		fsec;
+	fsec_t		fsec;
+#endif
 
 	if (TIMESTAMP_NOT_FINITE(timestamp))
 		PG_RETURN_NULL();
 
+#if 0
 	if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL) != 0)
 		elog(ERROR, "Unable to convert timestamp to date");
 
 	result = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - date2j(2000, 1, 1);
+#else
+	result = (timestamp / INT64CONST(86400000000));
+#endif
 
 	PG_RETURN_DATEADT(result);
 }
@@ -289,15 +358,29 @@ date_timestamptz(PG_FUNCTION_ARGS)
 		if (utime == -1)
 			elog(ERROR, "Unable to convert date to tm");
 
+#ifdef HAVE_INT64_TIMESTAMP
+		result = ((utime * INT64CONST(1000000))
+				  + ((date2j(1970, 1, 1) - date2j(2000, 1, 1)) * INT64CONST(86400000000)));
+#else
 		result = utime + ((date2j(1970, 1, 1) - date2j(2000, 1, 1)) * 86400.0);
+#endif
+#else
+#ifdef HAVE_INT64_TIMESTAMP
+		result = ((dateVal * INT64CONST(86400000000))
+			+ (CTimeZone * INT64CONST(1000000)));
 #else
 		result = dateVal * 86400.0 + CTimeZone;
+#endif
 #endif
 	}
 	else
 	{
+#ifdef HAVE_INT64_TIMESTAMP
+		result = (dateVal * INT64CONST(86400000000));
+#else
 		/* Outside of range for timezone support, so assume UTC */
 		result = dateVal * 86400.0;
+#endif
 	}
 
 	PG_RETURN_TIMESTAMP(result);
@@ -314,7 +397,7 @@ timestamptz_date(PG_FUNCTION_ARGS)
 	DateADT		result;
 	struct tm	tt,
 			   *tm = &tt;
-	double		fsec;
+	fsec_t		fsec;
 	int			tz;
 	char	   *tzn;
 
@@ -427,13 +510,12 @@ Datum
 time_in(PG_FUNCTION_ARGS)
 {
 	char	   *str = PG_GETARG_CSTRING(0);
-
 #ifdef NOT_USED
 	Oid			typelem = PG_GETARG_OID(1);
 #endif
 	int32		typmod = PG_GETARG_INT32(2);
 	TimeADT		result;
-	double		fsec;
+	fsec_t		fsec;
 	struct tm	tt,
 			   *tm = &tt;
 	int			nf;
@@ -446,13 +528,56 @@ time_in(PG_FUNCTION_ARGS)
 	 || (DecodeTimeOnly(field, ftype, nf, &dtype, tm, &fsec, NULL) != 0))
 		elog(ERROR, "Bad time external representation '%s'", str);
 
-	result = ((((tm->tm_hour * 60) + tm->tm_min) * 60) + tm->tm_sec + fsec);
-
+	tm2time(tm, fsec, &result);
 	AdjustTimeForTypmod(&result, typmod);
 
 	PG_RETURN_TIMEADT(result);
 }
 
+/* tm2time()
+ * Convert a tm structure to a time data type.
+ */
+int
+tm2time(struct tm * tm, fsec_t fsec, TimeADT *result)
+{
+#ifdef HAVE_INT64_TIMESTAMP
+	*result = ((((((tm->tm_hour * 60) + tm->tm_min) * 60) + tm->tm_sec)
+			   * INT64CONST(1000000)) + fsec);
+#else
+	*result = ((((tm->tm_hour * 60) + tm->tm_min) * 60) + tm->tm_sec + fsec);
+#endif
+	return 0;
+}
+
+/* time2tm()
+ * Convert time data type to POSIX time structure.
+ * 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
+time2tm(TimeADT time, struct tm *tm, fsec_t *fsec)
+{
+#ifdef HAVE_INT64_TIMESTAMP
+	tm->tm_hour = (time / INT64CONST(3600000000));
+	time -= (tm->tm_hour * INT64CONST(3600000000));
+	tm->tm_min = (time / INT64CONST(60000000));
+	time -= (tm->tm_min * INT64CONST(60000000));
+	tm->tm_sec = (time / INT64CONST(1000000));
+	time -= (tm->tm_sec * INT64CONST(1000000));
+	*fsec = time;
+#else
+	double		trem;
+
+	trem = time;
+	TMODULO(trem, tm->tm_hour, 3600e0);
+	TMODULO(trem, tm->tm_min, 60e0);
+	TMODULO(trem, tm->tm_sec, 1e0);
+	*fsec = trem;
+#endif
+
+	return 0;
+}
+
 Datum
 time_out(PG_FUNCTION_ARGS)
 {
@@ -460,16 +585,10 @@ time_out(PG_FUNCTION_ARGS)
 	char	   *result;
 	struct tm	tt,
 			   *tm = &tt;
-	double		fsec;
-	double		trem;
+	fsec_t		fsec;
 	char		buf[MAXDATELEN + 1];
 
-	trem = time;
-	TMODULO(trem, tm->tm_hour, 3600e0);
-	TMODULO(trem, tm->tm_min, 60e0);
-	TMODULO(trem, tm->tm_sec, 1e0);
-	fsec = trem;
-
+	time2tm(time, tm, &fsec);
 	EncodeTimeOnly(tm, fsec, NULL, DateStyle, buf);
 
 	result = pstrdup(buf);
@@ -496,21 +615,35 @@ time_scale(PG_FUNCTION_ARGS)
 static void
 AdjustTimeForTypmod(TimeADT *time, int32 typmod)
 {
-	if ((typmod >= 0) && (typmod <= 13))
+	if ((typmod >= 0) && (typmod <= MAX_TIME_PRECISION))
 	{
+#ifdef HAVE_INT64_TIMESTAMP
+		static int64 TimeScale = INT64CONST(1000000);
+#else
 		static double TimeScale = 1;
+#endif
 		static int32 TimeTypmod = 0;
 
 		if (typmod != TimeTypmod)
 		{
+#ifdef HAVE_INT64_TIMESTAMP
+			TimeScale = pow(10.0, (MAX_TIME_PRECISION-typmod));
+#else
 			TimeScale = pow(10.0, typmod);
+#endif
 			TimeTypmod = typmod;
 		}
 
+#ifdef HAVE_INT64_TIMESTAMP
+		*time = ((*time / TimeScale) * TimeScale);
+		if (*time >= INT64CONST(86400000000))
+			*time -= INT64CONST(86400000000);
+#else
 		*time = (rint(((double) *time) * TimeScale) / TimeScale);
 
 		if (*time >= 86400)
 			*time -= 86400;
+#endif
 	}
 
 	return;
@@ -738,15 +871,56 @@ timestamp_time(PG_FUNCTION_ARGS)
 	TimeADT		result;
 	struct tm	tt,
 			   *tm = &tt;
-	double		fsec;
+	fsec_t		fsec;
 
 	if (TIMESTAMP_NOT_FINITE(timestamp))
 		PG_RETURN_NULL();
 
 	if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL) != 0)
-		elog(ERROR, "Unable to convert timestamp to date");
+		elog(ERROR, "Unable to convert timestamp to time");
+
+#ifdef HAVE_INT64_TIMESTAMP
+	/* Could also do this with
+	 * time = (timestamp / 86400000000 * 86400000000) - timestamp;
+	 */
+	result = ((((((tm->tm_hour * 60) + tm->tm_min) * 60) + tm->tm_sec)
+			   * INT64CONST(1000000)) + fsec);
+#else
+	result = ((((tm->tm_hour * 60) + tm->tm_min) * 60) + tm->tm_sec + fsec);
+#endif
+
+	PG_RETURN_TIMEADT(result);
+}
+
+/* timestamptz_time()
+ * Convert timestamptz to time data type.
+ */
+Datum
+timestamptz_time(PG_FUNCTION_ARGS)
+{
+	TimestampTz timestamp = PG_GETARG_TIMESTAMP(0);
+	TimeADT		result;
+	struct tm	tt,
+			   *tm = &tt;
+	int			tz;
+	fsec_t		fsec;
+	char	   *tzn;
 
+	if (TIMESTAMP_NOT_FINITE(timestamp))
+		PG_RETURN_NULL();
+
+	if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn) != 0)
+		elog(ERROR, "Unable to convert timestamptz to time");
+
+#ifdef HAVE_INT64_TIMESTAMP
+	/* Could also do this with
+	 * time = (timestamp / 86400000000 * 86400000000) - timestamp;
+	 */
+	result = ((((((tm->tm_hour * 60) + tm->tm_min) * 60) + tm->tm_sec)
+			   * INT64CONST(1000000)) + fsec);
+#else
 	result = ((((tm->tm_hour * 60) + tm->tm_min) * 60) + tm->tm_sec + fsec);
+#endif
 
 	PG_RETURN_TIMEADT(result);
 }
@@ -793,10 +967,18 @@ interval_time(PG_FUNCTION_ARGS)
 {
 	Interval   *span = PG_GETARG_INTERVAL_P(0);
 	TimeADT		result;
+
+#ifdef HAVE_INT64_TIMESTAMP
+	result = span->time;
+	if ((result >= INT64CONST(86400000000))
+		|| (result <= INT64CONST(-86400000000)))
+		result -= (result / INT64CONST(1000000) * INT64CONST(1000000));
+#else
 	Interval	span1;
 
 	result = span->time;
 	TMODULO(result, span1.time, 86400e0);
+#endif
 
 	PG_RETURN_TIMEADT(result);
 }
@@ -813,7 +995,7 @@ time_mi_time(PG_FUNCTION_ARGS)
 
 	result = (Interval *) palloc(sizeof(Interval));
 
-	result->time = time1 - time2;
+	result->time = (time1 - time2);
 	result->month = 0;
 
 	PG_RETURN_INTERVAL_P(result);
@@ -828,12 +1010,20 @@ time_pl_interval(PG_FUNCTION_ARGS)
 	TimeADT		time = PG_GETARG_TIMEADT(0);
 	Interval   *span = PG_GETARG_INTERVAL_P(1);
 	TimeADT		result;
+
+#ifdef HAVE_INT64_TIMESTAMP
+	result = (time + span->time);
+	result -= (result / INT64CONST(86400000000) * INT64CONST(86400000000));
+	if (result < INT64CONST(0))
+		result += INT64CONST(86400000000);
+#else
 	TimeADT		time1;
 
 	result = (time + span->time);
 	TMODULO(result, time1, 86400e0);
 	if (result < 0)
 		result += 86400;
+#endif
 
 	PG_RETURN_TIMEADT(result);
 }
@@ -847,12 +1037,20 @@ time_mi_interval(PG_FUNCTION_ARGS)
 	TimeADT		time = PG_GETARG_TIMEADT(0);
 	Interval   *span = PG_GETARG_INTERVAL_P(1);
 	TimeADT		result;
+
+#ifdef HAVE_INT64_TIMESTAMP
+	result = (time - span->time);
+	result -= (result / INT64CONST(86400000000) * INT64CONST(86400000000));
+	if (result < INT64CONST(0))
+		result += INT64CONST(86400000000);
+#else
 	TimeADT		time1;
 
 	result = (time - span->time);
 	TMODULO(result, time1, 86400e0);
 	if (result < 0)
 		result += 86400;
+#endif
 
 	PG_RETURN_TIMEADT(result);
 }
@@ -926,11 +1124,137 @@ text_time(PG_FUNCTION_ARGS)
 							   Int32GetDatum(-1));
 }
 
+/* time_part()
+ * Extract specified field from time type.
+ */
+Datum
+time_part(PG_FUNCTION_ARGS)
+{
+	text	   *units = PG_GETARG_TEXT_P(0);
+	TimeADT		time = PG_GETARG_TIMEADT(1);
+	float8		result;
+	int			type,
+				val;
+	int			i;
+	char	   *up,
+			   *lp,
+				lowunits[MAXDATELEN + 1];
+
+	if (VARSIZE(units) - VARHDRSZ > MAXDATELEN)
+		elog(ERROR, "TIME units '%s' not recognized",
+			 DatumGetCString(DirectFunctionCall1(textout,
+											   PointerGetDatum(units))));
+	up = VARDATA(units);
+	lp = lowunits;
+	for (i = 0; i < (VARSIZE(units) - VARHDRSZ); i++)
+		*lp++ = tolower((unsigned char) *up++);
+	*lp = '\0';
+
+	type = DecodeUnits(0, lowunits, &val);
+	if (type == UNKNOWN_FIELD)
+		type = DecodeSpecial(0, lowunits, &val);
+
+	if (type == UNITS)
+	{
+		fsec_t		fsec;
+		struct tm	tt,
+				   *tm = &tt;
+
+		time2tm(time, tm, &fsec);
+
+		switch (val)
+		{
+			case DTK_MICROSEC:
+#ifdef HAVE_INT64_TIMESTAMP
+				result = ((tm->tm_sec * INT64CONST(1000000)) + fsec);
+#else
+				result = ((tm->tm_sec + fsec) * 1000000);
+#endif
+				break;
+
+			case DTK_MILLISEC:
+#ifdef HAVE_INT64_TIMESTAMP
+				result = ((tm->tm_sec * INT64CONST(1000))
+						  + (fsec / INT64CONST(1000)));
+#else
+				result = ((tm->tm_sec + fsec) * 1000);
+#endif
+				break;
+
+			case DTK_SECOND:
+#ifdef HAVE_INT64_TIMESTAMP
+				result = (tm->tm_sec + (fsec / INT64CONST(1000000)));
+#else
+				result = (tm->tm_sec + fsec);
+#endif
+				break;
+
+			case DTK_MINUTE:
+				result = tm->tm_min;
+				break;
+
+			case DTK_HOUR:
+				result = tm->tm_hour;
+				break;
+
+			case DTK_TZ:
+			case DTK_TZ_MINUTE:
+			case DTK_TZ_HOUR:
+			case DTK_DAY:
+			case DTK_MONTH:
+			case DTK_QUARTER:
+			case DTK_YEAR:
+			case DTK_DECADE:
+			case DTK_CENTURY:
+			case DTK_MILLENNIUM:
+			default:
+				elog(ERROR, "TIME units '%s' not supported",
+					 DatumGetCString(DirectFunctionCall1(textout,
+											   PointerGetDatum(units))));
+				result = 0;
+		}
+	}
+	else if ((type == RESERV) && (val == DTK_EPOCH))
+	{
+#ifdef HAVE_INT64_TIMESTAMP
+		result = (time / 1000000e0);
+#else
+		result = time;
+#endif
+	}
+	else
+	{
+		elog(ERROR, "TIME units '%s' not recognized",
+			 DatumGetCString(DirectFunctionCall1(textout,
+											   PointerGetDatum(units))));
+		result = 0;
+	}
+
+	PG_RETURN_FLOAT8(result);
+}
+
 
 /*****************************************************************************
  *	 Time With Time Zone ADT
  *****************************************************************************/
 
+/* tm2timetz()
+ * Convert a tm structure to a time data type.
+ */
+int
+tm2timetz(struct tm * tm, fsec_t fsec, int tz, TimeTzADT *result)
+{
+#ifdef HAVE_INT64_TIMESTAMP
+	result->time = ((((((tm->tm_hour * 60) + tm->tm_min) * 60) + tm->tm_sec)
+					 * INT64CONST(1000000)) + fsec);
+#else
+	result->time = ((((tm->tm_hour * 60) + tm->tm_min) * 60) + tm->tm_sec + fsec);
+#endif
+	result->zone = tz;
+
+	return 0;
+}
+
 Datum
 timetz_in(PG_FUNCTION_ARGS)
 {
@@ -941,7 +1265,7 @@ timetz_in(PG_FUNCTION_ARGS)
 #endif
 	int32		typmod = PG_GETARG_INT32(2);
 	TimeTzADT  *result;
-	double		fsec;
+	fsec_t		fsec;
 	struct tm	tt,
 			   *tm = &tt;
 	int			tz;
@@ -956,10 +1280,7 @@ timetz_in(PG_FUNCTION_ARGS)
 		elog(ERROR, "Bad time external representation '%s'", str);
 
 	result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
-
-	result->time = ((((tm->tm_hour * 60) + tm->tm_min) * 60) + tm->tm_sec + fsec);
-	result->zone = tz;
-
+	tm2timetz(tm, fsec, tz, result);
 	AdjustTimeForTypmod(&(result->time), typmod);
 
 	PG_RETURN_TIMETZADT_P(result);
@@ -972,23 +1293,46 @@ timetz_out(PG_FUNCTION_ARGS)
 	char	   *result;
 	struct tm	tt,
 			   *tm = &tt;
-	double		fsec;
+	fsec_t		fsec;
 	int			tz;
-	double		trem;
 	char		buf[MAXDATELEN + 1];
 
+	timetz2tm(time, tm, &fsec, &tz);
+	EncodeTimeOnly(tm, fsec, &tz, DateStyle, buf);
+
+	result = pstrdup(buf);
+	PG_RETURN_CSTRING(result);
+}
+
+/* timetz2tm()
+ * Convert TIME WITH TIME ZONE data type to POSIX time structure.
+ * 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
+timetz2tm(TimeTzADT *time, struct tm *tm, fsec_t *fsec, int *tzp)
+{
+#ifdef HAVE_INT64_TIMESTAMP
+	tm->tm_hour = (time->time / INT64CONST(3600000000));
+	time->time -= (tm->tm_hour * INT64CONST(3600000000));
+	tm->tm_min = (time->time / INT64CONST(60000000));
+	time->time -= (tm->tm_min * INT64CONST(60000000));
+	tm->tm_sec = (time->time / INT64CONST(1000000));
+	*fsec = (time->time - (tm->tm_sec * INT64CONST(1000000)));
+#else
+	double		trem;
+
 	trem = time->time;
 	TMODULO(trem, tm->tm_hour, 3600e0);
 	TMODULO(trem, tm->tm_min, 60e0);
 	TMODULO(trem, tm->tm_sec, 1e0);
-	fsec = trem;
-
-	tz = time->zone;
+	*fsec = trem;
+#endif
 
-	EncodeTimeOnly(tm, fsec, &tz, DateStyle, buf);
+	if (tzp != NULL)
+		*tzp = time->zone;
 
-	result = pstrdup(buf);
-	PG_RETURN_CSTRING(result);
+	return 0;
 }
 
 /* timetz_scale()
@@ -1116,7 +1460,7 @@ timetz_hash(PG_FUNCTION_ARGS)
 	 * sizeof(TimeTzADT), so that any garbage pad bytes in the structure
 	 * won't be included in the hash!
 	 */
-	return hash_any((unsigned char *) key, sizeof(double) + sizeof(int4));
+	return hash_any((unsigned char *) key, sizeof(key->time) + sizeof(key->zone));
 }
 
 Datum
@@ -1154,14 +1498,24 @@ timetz_pl_interval(PG_FUNCTION_ARGS)
 	TimeTzADT  *time = PG_GETARG_TIMETZADT_P(0);
 	Interval   *span = PG_GETARG_INTERVAL_P(1);
 	TimeTzADT  *result;
+#ifndef HAVE_INT64_TIMESTAMP
 	TimeTzADT	time1;
+#endif
 
 	result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
 
+#ifdef HAVE_INT64_TIMESTAMP
+	result->time = (time->time + span->time);
+	result->time -= (result->time / INT64CONST(86400000000) * INT64CONST(86400000000));
+	if (result->time < INT64CONST(0))
+		result->time += INT64CONST(86400000000);
+#else
 	result->time = (time->time + span->time);
 	TMODULO(result->time, time1.time, 86400e0);
 	if (result->time < 0)
 		result->time += 86400;
+#endif
+
 	result->zone = time->zone;
 
 	PG_RETURN_TIMETZADT_P(result);
@@ -1176,14 +1530,24 @@ timetz_mi_interval(PG_FUNCTION_ARGS)
 	TimeTzADT  *time = PG_GETARG_TIMETZADT_P(0);
 	Interval   *span = PG_GETARG_INTERVAL_P(1);
 	TimeTzADT  *result;
+#ifndef HAVE_INT64_TIMESTAMP
 	TimeTzADT	time1;
+#endif
 
 	result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
 
+#ifdef HAVE_INT64_TIMESTAMP
+	result->time = (time->time - span->time);
+	result->time -= (result->time / INT64CONST(86400000000) * INT64CONST(86400000000));
+	if (result->time < INT64CONST(0))
+		result->time += INT64CONST(86400000000);
+#else
 	result->time = (time->time - span->time);
 	TMODULO(result->time, time1.time, 86400e0);
 	if (result->time < 0)
 		result->time += 86400;
+#endif
+
 	result->zone = time->zone;
 
 	PG_RETURN_TIMETZADT_P(result);
@@ -1336,9 +1700,11 @@ time_timetz(PG_FUNCTION_ARGS)
 	TimeTzADT  *result;
 	struct tm	tt,
 			   *tm = &tt;
+	fsec_t		fsec;
 	int			tz;
 
 	GetCurrentTime(tm);
+	time2tm(time, tm, &fsec);
 	tz = DetermineLocalTimeZone(tm);
 
 	result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
@@ -1361,19 +1727,18 @@ timestamptz_timetz(PG_FUNCTION_ARGS)
 	struct tm	tt,
 			   *tm = &tt;
 	int			tz;
-	double		fsec;
+	fsec_t		fsec;
 	char	   *tzn;
 
 	if (TIMESTAMP_NOT_FINITE(timestamp))
 		PG_RETURN_NULL();
 
 	if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn) != 0)
-		elog(ERROR, "Unable to convert timestamp to date");
+		elog(ERROR, "Unable to convert timestamptz to timetz");
 
 	result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
 
-	result->time = ((((tm->tm_hour * 60) + tm->tm_min) * 60) + tm->tm_sec + fsec);
-	result->zone = tz;
+	tm2timetz(tm, fsec, tz, result);
 
 	PG_RETURN_TIMETZADT_P(result);
 }
@@ -1392,7 +1757,12 @@ datetimetz_timestamptz(PG_FUNCTION_ARGS)
 	TimeTzADT  *time = PG_GETARG_TIMETZADT_P(1);
 	TimestampTz result;
 
-	result = date * 86400.0 + time->time + time->zone;
+#ifdef HAVE_INT64_TIMESTAMP
+	result = (((date * INT64CONST(86400000000)) + time->time)
+		+ (time->zone * INT64CONST(1000000)));
+#else
+	result = (((date * 86400.0) + time->time) + time->zone);
+#endif
 
 	PG_RETURN_TIMESTAMP(result);
 }
@@ -1486,19 +1856,13 @@ timetz_part(PG_FUNCTION_ARGS)
 
 	if (type == UNITS)
 	{
-		double		trem;
 		double		dummy;
 		int			tz;
-		double		fsec;
+		fsec_t		fsec;
 		struct tm	tt,
 				   *tm = &tt;
 
-		trem = time->time;
-		TMODULO(trem, tm->tm_hour, 3600e0);
-		TMODULO(trem, tm->tm_min, 60e0);
-		TMODULO(trem, tm->tm_sec, 1e0);
-		fsec = trem;
-		tz = time->zone;
+		timetz2tm(time, tm, &fsec, &tz);
 
 		switch (val)
 		{
@@ -1517,15 +1881,28 @@ timetz_part(PG_FUNCTION_ARGS)
 				break;
 
 			case DTK_MICROSEC:
+#ifdef HAVE_INT64_TIMESTAMP
+				result = ((tm->tm_sec * INT64CONST(1000000)) + fsec);
+#else
 				result = ((tm->tm_sec + fsec) * 1000000);
+#endif
 				break;
 
 			case DTK_MILLISEC:
+#ifdef HAVE_INT64_TIMESTAMP
+				result = ((tm->tm_sec * INT64CONST(1000))
+						  + (fsec / INT64CONST(1000)));
+#else
 				result = ((tm->tm_sec + fsec) * 1000);
+#endif
 				break;
 
 			case DTK_SECOND:
+#ifdef HAVE_INT64_TIMESTAMP
+				result = (tm->tm_sec + (fsec / INT64CONST(1000000)));
+#else
 				result = (tm->tm_sec + fsec);
+#endif
 				break;
 
 			case DTK_MINUTE:
@@ -1551,7 +1928,13 @@ timetz_part(PG_FUNCTION_ARGS)
 		}
 	}
 	else if ((type == RESERV) && (val == DTK_EPOCH))
-		result = time->time - time->zone;
+	{
+#ifdef HAVE_INT64_TIMESTAMP
+		result = ((time->time / 1000000e0) - time->zone);
+#else
+		result = (time->time - time->zone);
+#endif
+	}
 	else
 	{
 		elog(ERROR, "TIMETZ units '%s' not recognized",
@@ -1598,10 +1981,18 @@ timetz_zone(PG_FUNCTION_ARGS)
 	if ((type == TZ) || (type == DTZ))
 	{
 		tz = val * 60;
-		time1 = time->time - time->zone + tz;
+#ifdef HAVE_INT64_TIMESTAMP
+		time1 = (time->time - ((time->zone + tz) * INT64CONST(1000000)));
+		result->time -= ((result->time / time1) * time1);
+		if (result->time < INT64CONST(0))
+			result->time += INT64CONST(86400000000);
+#else
+		time1 = (time->time - time->zone + tz);
 		TMODULO(result->time, time1, 86400e0);
 		if (result->time < 0)
 			result->time += 86400;
+#endif
+
 		result->zone = tz;
 	}
 	else
@@ -1622,7 +2013,6 @@ timetz_izone(PG_FUNCTION_ARGS)
 	Interval   *zone = PG_GETARG_INTERVAL_P(0);
 	TimeTzADT  *time = PG_GETARG_TIMETZADT_P(1);
 	TimeTzADT  *result;
-	TimeADT		time1;
 	int			tz;
 
 	if (zone->month != 0)
@@ -1630,14 +2020,28 @@ timetz_izone(PG_FUNCTION_ARGS)
 			 DatumGetCString(DirectFunctionCall1(interval_out,
 												 PointerGetDatum(zone))));
 
+#ifdef HAVE_INT64_TIMESTAMP
+	tz = -(zone->time / INT64CONST(1000000));
+#else
 	tz = -(zone->time);
+#endif
 
 	result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
 
-	time1 = time->time - time->zone + tz;
-	TMODULO(result->time, time1, 86400e0);
-	if (result->time < 0)
+#ifdef HAVE_INT64_TIMESTAMP
+	result->time = (time->time + ((time->zone - tz) * INT64CONST(1000000)));
+	while (result->time < INT64CONST(0))
+		result->time += INT64CONST(86400000000);
+	while (result->time >= INT64CONST(86400000000))
+		result->time -= INT64CONST(86400000000);
+#else
+	result->time = (time->time + (time->zone - tz));
+	while (result->time < 0)
 		result->time += 86400;
+	while (result->time >= 86400)
+		result->time -= 86400;
+#endif
+
 	result->zone = tz;
 
 	PG_RETURN_TIMETZADT_P(result);
diff --git a/src/backend/utils/adt/datetime.c b/src/backend/utils/adt/datetime.c
index 1dd540abb7f13457ec31ca1a933c9a28894bf761..1a908d9d6b7d15801f1e383b8c964f659322b942 100644
--- a/src/backend/utils/adt/datetime.c
+++ b/src/backend/utils/adt/datetime.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v 1.88 2002/02/25 16:17:04 thomas Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v 1.89 2002/04/21 19:48:12 thomas Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -28,12 +28,12 @@
 
 static int DecodeNumber(int flen, char *field,
 			 int fmask, int *tmask,
-			 struct tm * tm, double *fsec, int *is2digits);
+			 struct tm * tm, fsec_t *fsec, int *is2digits);
 static int DecodeNumberField(int len, char *str,
 				  int fmask, int *tmask,
-				  struct tm * tm, double *fsec, int *is2digits);
+				  struct tm * tm, fsec_t *fsec, int *is2digits);
 static int DecodeTime(char *str, int fmask, int *tmask,
-		   struct tm * tm, double *fsec);
+		   struct tm * tm, fsec_t *fsec);
 static int	DecodeTimezone(char *str, int *tzp);
 static datetkn *datebsearch(char *key, datetkn *base, unsigned int nel);
 static int	DecodeDate(char *str, int fmask, int *tmask, struct tm * tm);
@@ -865,7 +865,7 @@ ParseDateTime(char *timestr, char *lowstr,
  */
 int
 DecodeDateTime(char **field, int *ftype, int nf,
-			   int *dtype, struct tm * tm, double *fsec, int *tzp)
+			   int *dtype, struct tm * tm, fsec_t *fsec, int *tzp)
 {
 	int			fmask = 0,
 				tmask,
@@ -1095,9 +1095,15 @@ DecodeDateTime(char **field, int *ftype, int nf,
 							tmask = DTK_M(SECOND);
 							if (*cp == '.')
 							{
-								*fsec = strtod(cp, &cp);
+								double frac;
+								frac = strtod(cp, &cp);
 								if (*cp != '\0')
 									return -1;
+#ifdef HAVE_INT64_TIMESTAMP
+								*fsec = frac * 1000000;
+#else
+								*fsec = frac;
+#endif
 							}
 							break;
 
@@ -1113,6 +1119,7 @@ DecodeDateTime(char **field, int *ftype, int nf,
 							 ***/
 							tmask = DTK_DATE_M;
 							j2date(val, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
+							/* fractional Julian Day? */
 							if (*cp == '.')
 							{
 								double time;
@@ -1122,9 +1129,11 @@ DecodeDateTime(char **field, int *ftype, int nf,
 									return -1;
 
 								tmask |= DTK_TIME_M;
-								dt2time((time*86400), &tm->tm_hour, &tm->tm_min, fsec);
-								tm->tm_sec = *fsec;
-								*fsec -= tm->tm_sec;
+#ifdef HAVE_INT64_TIMESTAMP
+								dt2time((time*86400000000), &tm->tm_hour, &tm->tm_min, &tm->tm_sec, fsec);
+#else
+								dt2time((time*86400), &tm->tm_hour, &tm->tm_min, &tm->tm_sec, fsec);
+#endif
 							}
 							break;
 
@@ -1505,7 +1514,7 @@ DetermineLocalTimeZone(struct tm * tm)
  */
 int
 DecodeTimeOnly(char **field, int *ftype, int nf,
-			   int *dtype, struct tm * tm, double *fsec, int *tzp)
+			   int *dtype, struct tm * tm, fsec_t *fsec, int *tzp)
 {
 	int			fmask = 0,
 				tmask,
@@ -1729,9 +1738,11 @@ DecodeTimeOnly(char **field, int *ftype, int nf,
 									return -1;
 
 								tmask |= DTK_TIME_M;
-								dt2time((time*86400), &tm->tm_hour, &tm->tm_min, fsec);
-								tm->tm_sec = *fsec;
-								*fsec -= tm->tm_sec;
+#ifdef HAVE_INT64_TIMESTAMP
+								dt2time((time*86400000000), &tm->tm_hour, &tm->tm_min, &tm->tm_sec, fsec);
+#else
+								dt2time((time*86400), &tm->tm_hour, &tm->tm_min, &tm->tm_sec, fsec);
+#endif
 							}
 							break;
 
@@ -1925,10 +1936,18 @@ DecodeTimeOnly(char **field, int *ftype, int nf,
 	else if ((mer == PM) && (tm->tm_hour != 12))
 		tm->tm_hour += 12;
 
+#ifdef HAVE_INT64_TIMESTAMP
+	if (((tm->tm_hour < 0) || (tm->tm_hour > 23))
+		|| ((tm->tm_min < 0) || (tm->tm_min > 59))
+		|| ((tm->tm_sec < 0) || (tm->tm_sec > 60))
+		|| (*fsec < INT64CONST(0)) || (*fsec >= INT64CONST(1000000)))
+		return -1;
+#else
 	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;
+#endif
 
 	if ((fmask & DTK_TIME_M) != DTK_TIME_M)
 		return -1;
@@ -1973,7 +1992,7 @@ DecodeTimeOnly(char **field, int *ftype, int nf,
 static int
 DecodeDate(char *str, int fmask, int *tmask, struct tm * tm)
 {
-	double		fsec;
+	fsec_t		fsec;
 
 	int			nf = 0;
 	int			i,
@@ -2100,7 +2119,7 @@ DecodeDate(char *str, int fmask, int *tmask, struct tm * tm)
  *	can be used to represent time spans.
  */
 static int
-DecodeTime(char *str, int fmask, int *tmask, struct tm * tm, double *fsec)
+DecodeTime(char *str, int fmask, int *tmask, struct tm * tm, fsec_t *fsec)
 {
 	char	   *cp;
 
@@ -2115,12 +2134,10 @@ DecodeTime(char *str, int fmask, int *tmask, struct tm * tm, double *fsec)
 	{
 		tm->tm_sec = 0;
 		*fsec = 0;
-
 	}
 	else if (*cp != ':')
 	{
 		return -1;
-
 	}
 	else
 	{
@@ -2130,9 +2147,22 @@ DecodeTime(char *str, int fmask, int *tmask, struct tm * tm, double *fsec)
 			*fsec = 0;
 		else if (*cp == '.')
 		{
+#ifdef HAVE_INT64_TIMESTAMP
+			char fstr[MAXDATELEN + 1];
+
+			/* OK, we have at most six digits to work with.
+			 * Let's construct a string and then do the conversion
+			 * to an integer.
+			 */
+			strncpy(fstr, (cp+1), 7);
+			strcpy((fstr+strlen(fstr)), "000000");
+			*(fstr+6) = '\0';
+			*fsec = strtol(fstr, &cp, 10);
+#else
 			str = cp;
 			*fsec = strtod(str, &cp);
-			if (cp == str)
+#endif
+			if (*cp != '\0')
 				return -1;
 		}
 		else
@@ -2140,10 +2170,19 @@ DecodeTime(char *str, int fmask, int *tmask, struct tm * tm, double *fsec)
 	}
 
 	/* do a sanity check */
+#ifdef HAVE_INT64_TIMESTAMP
+	if ((tm->tm_hour < 0)
+		|| (tm->tm_min < 0) || (tm->tm_min > 59)
+		|| (tm->tm_sec < 0) || (tm->tm_sec > 59)
+		|| (*fsec >= INT64CONST(1000000)))
+		return -1;
+#else
 	if ((tm->tm_hour < 0)
 		|| (tm->tm_min < 0) || (tm->tm_min > 59)
-		|| (tm->tm_sec < 0) || (tm->tm_sec > 59))
+		|| (tm->tm_sec < 0) || (tm->tm_sec > 59)
+		|| (*fsec >= 1))
 		return -1;
+#endif
 
 	return 0;
 }	/* DecodeTime() */
@@ -2154,7 +2193,7 @@ DecodeTime(char *str, int fmask, int *tmask, struct tm * tm, double *fsec)
  */
 static int
 DecodeNumber(int flen, char *str, int fmask,
-			 int *tmask, struct tm * tm, double *fsec, int *is2digits)
+			 int *tmask, struct tm * tm, fsec_t *fsec, int *is2digits)
 {
 	int			val;
 	char	   *cp;
@@ -2193,7 +2232,6 @@ DecodeNumber(int flen, char *str, int fmask,
 		tm->tm_yday = val;
 		j2date((date2j(tm->tm_year, 1, 1) + tm->tm_yday - 1),
 			   &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
-
 	}
 
 	/***
@@ -2225,7 +2263,6 @@ DecodeNumber(int flen, char *str, int fmask,
 	{
 		*tmask = DTK_M(MONTH);
 		tm->tm_mon = val;
-
 	}
 	/* no year and EuroDates enabled? then could be day */
 	else if ((EuroDates || (fmask & DTK_M(MONTH)))
@@ -2275,7 +2312,7 @@ DecodeNumber(int flen, char *str, int fmask,
  */
 static int
 DecodeNumberField(int len, char *str, int fmask,
-				  int *tmask, struct tm * tm, double *fsec, int *is2digits)
+				  int *tmask, struct tm * tm, fsec_t *fsec, int *is2digits)
 {
 	char	   *cp;
 
@@ -2284,7 +2321,20 @@ DecodeNumberField(int len, char *str, int fmask,
 	 */
 	if ((cp = strchr(str, '.')) != NULL)
 	{
+#ifdef HAVE_INT64_TIMESTAMP
+			char fstr[MAXDATELEN + 1];
+
+			/* OK, we have at most six digits to care about.
+			 * Let's construct a string and then do the conversion
+			 * to an integer.
+			 */
+			strcpy(fstr, (cp+1));
+			strcpy((fstr+strlen(fstr)), "000000");
+			*(fstr+6) = '\0';
+			*fsec = strtol(fstr, NULL, 10);
+#else
 		*fsec = strtod(cp, NULL);
+#endif
 		*cp = '\0';
 		len = strlen(str);
 	}
@@ -2501,7 +2551,7 @@ DecodeSpecial(int field, char *lowtoken, int *val)
 }	/* DecodeSpecial() */
 
 
-/* DecodeDateDelta()
+/* DecodeInterval()
  * Interpret previously parsed fields for general time interval.
  * Return 0 if decoded and -1 if problems.
  *
@@ -2512,7 +2562,7 @@ DecodeSpecial(int field, char *lowtoken, int *val)
  *	preceding an hh:mm:ss field. - thomas 1998-04-30
  */
 int
-DecodeDateDelta(char **field, int *ftype, int nf, int *dtype, struct tm * tm, double *fsec)
+DecodeInterval(char **field, int *ftype, int nf, int *dtype, struct tm * tm, fsec_t *fsec)
 {
 	int			is_before = FALSE;
 
@@ -2523,7 +2573,6 @@ DecodeDateDelta(char **field, int *ftype, int nf, int *dtype, struct tm * tm, do
 	int			i;
 	int			val;
 	double		fval;
-	double		sec;
 
 	*dtype = DTK_DELTA;
 
@@ -2631,51 +2680,113 @@ DecodeDateDelta(char **field, int *ftype, int nf, int *dtype, struct tm * tm, do
 				switch (type)
 				{
 					case DTK_MICROSEC:
+#ifdef HAVE_INT64_TIMESTAMP
+						*fsec += (val + fval);
+#else
 						*fsec += ((val + fval) * 1e-6);
+#endif
 						break;
 
 					case DTK_MILLISEC:
+#ifdef HAVE_INT64_TIMESTAMP
+						*fsec += ((val + fval) * 1000);
+#else
 						*fsec += ((val + fval) * 1e-3);
+#endif
 						break;
 
 					case DTK_SECOND:
 						tm->tm_sec += val;
+#ifdef HAVE_INT64_TIMESTAMP
+						*fsec += (fval * 1000000);
+#else
 						*fsec += fval;
+#endif
 						tmask = DTK_M(SECOND);
 						break;
 
 					case DTK_MINUTE:
 						tm->tm_min += val;
 						if (fval != 0)
-							tm->tm_sec += (fval * 60);
+						{
+							int sec;
+							fval *= 60;
+							sec = fval;
+							tm->tm_sec += sec;
+#ifdef HAVE_INT64_TIMESTAMP
+							*fsec += ((fval - sec) * 1000000);
+#else
+							*fsec += (fval - sec);
+#endif
+						}
 						tmask = DTK_M(MINUTE);
 						break;
 
 					case DTK_HOUR:
 						tm->tm_hour += val;
 						if (fval != 0)
-							tm->tm_sec += (fval * 3600);
+						{
+							int sec;
+							fval *= 3600;
+							sec = fval;
+							tm->tm_sec += sec;
+#ifdef HAVE_INT64_TIMESTAMP
+							*fsec += ((fval - sec) * 1000000);
+#else
+							*fsec += (fval - sec);
+#endif
+						}
 						tmask = DTK_M(HOUR);
 						break;
 
 					case DTK_DAY:
 						tm->tm_mday += val;
 						if (fval != 0)
-							tm->tm_sec += (fval * 86400);
+						{
+							int sec;
+							fval *= 86400;
+							sec = fval;
+							tm->tm_sec += sec;
+#ifdef HAVE_INT64_TIMESTAMP
+							*fsec += ((fval - sec) * 1000000);
+#else
+							*fsec += (fval - sec);
+#endif
+						}
 						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));
+						{
+							int sec;
+							fval *= (7*86400);
+							sec = fval;
+							tm->tm_sec += sec;
+#ifdef HAVE_INT64_TIMESTAMP
+							*fsec += ((fval - sec) * 1000000);
+#else
+							*fsec += (fval - sec);
+#endif
+						}
 						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));
+						{
+							int sec;
+							fval *= (30*86400);
+							sec = fval;
+							tm->tm_sec += sec;
+#ifdef HAVE_INT64_TIMESTAMP
+							*fsec += ((fval - sec) * 1000000);
+#else
+							*fsec += (fval - sec);
+#endif
+						}
 						tmask = DTK_M(MONTH);
 						break;
 
@@ -2751,7 +2862,14 @@ DecodeDateDelta(char **field, int *ftype, int nf, int *dtype, struct tm * tm, do
 
 	if (*fsec != 0)
 	{
+		int		sec;
+
+#ifdef HAVE_INT64_TIMESTAMP
+		sec = (*fsec / INT64CONST(1000000));
+		*fsec -= (sec * INT64CONST(1000000));
+#else
 		TMODULO(*fsec, sec, 1e0);
+#endif
 		tm->tm_sec += sec;
 	}
 
@@ -2768,7 +2886,7 @@ DecodeDateDelta(char **field, int *ftype, int nf, int *dtype, struct tm * tm, do
 
 	/* ensure that at least one time field has been found */
 	return (fmask != 0) ? 0 : -1;
-}	/* DecodeDateDelta() */
+}	/* DecodeInterval() */
 
 
 /* DecodeUnits()
@@ -2899,14 +3017,18 @@ EncodeDateOnly(struct tm * tm, int style, char *str)
  * Encode time fields only.
  */
 int
-EncodeTimeOnly(struct tm * tm, double fsec, int *tzp, int style, char *str)
+EncodeTimeOnly(struct tm * tm, fsec_t fsec, int *tzp, int style, char *str)
 {
-	double		sec;
+#ifndef HAVE_INT64_TIMESTAMP
+	fsec_t		sec;
+#endif
 
 	if ((tm->tm_hour < 0) || (tm->tm_hour > 24))
 		return -1;
 
+#ifndef HAVE_INT64_TIMESTAMP
 	sec = (tm->tm_sec + fsec);
+#endif
 
 	sprintf(str, "%02d:%02d", tm->tm_hour, tm->tm_min);
 
@@ -2919,14 +3041,23 @@ EncodeTimeOnly(struct tm * tm, double fsec, int *tzp, int style, char *str)
 	 */
 	if (fsec != 0)
 	{
+#ifdef HAVE_INT64_TIMESTAMP
+		sprintf((str + strlen(str)), ":%02d", tm->tm_sec);
+		sprintf((str + strlen(str)), ".%06d", fsec);
+#else
 		sprintf((str + strlen(str)), ":%013.10f", sec);
+#endif
 		/* chop off trailing pairs of zeros... */
 		while ((strcmp((str + strlen(str) - 2), "00") == 0)
 			   && (*(str + strlen(str) - 3) != '.'))
 			*(str + strlen(str) - 2) = '\0';
 	}
 	else
+#ifdef HAVE_INT64_TIMESTAMP
+		sprintf((str + strlen(str)), ":%02d", tm->tm_sec);
+#else
 		sprintf((str + strlen(str)), ":%02.0f", sec);
+#endif
 
 	if (tzp != NULL)
 	{
@@ -2954,158 +3085,191 @@ EncodeTimeOnly(struct tm * tm, double fsec, int *tzp, int style, char *str)
  *	European - dd/mm/yyyy
  */
 int
-EncodeDateTime(struct tm * tm, double fsec, int *tzp, char **tzn, int style, char *str)
+EncodeDateTime(struct tm * tm, fsec_t fsec, int *tzp, char **tzn, int style, char *str)
 {
 	int			day,
 				hour,
 				min;
-	double		sec;
+#ifndef HAVE_INT64_TIMESTAMP
+	fsec_t		sec;
+#endif
 
-	if ((tm->tm_mon < 1) || (tm->tm_mon > 12))
-		return -1;
+	/* Why are we checking only the month field? Change this to an assert...
+	 * if ((tm->tm_mon < 1) || (tm->tm_mon > 12))
+	 *  return -1;
+	 */
+	Assert((tm->tm_mon >= 1) && (tm->tm_mon <= 12));
 
+#ifndef HAVE_INT64_TIMESTAMP
 	sec = (tm->tm_sec + fsec);
+#endif
 
 	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);
+			/* Compatible with ISO-8601 date formats */
 
-				/*
-				 * If we have fractional seconds, then include a decimal
-				 * point We will do up to 6 fractional digits, and we have
-				 * rounded any inputs to eliminate anything to the right
-				 * of 6 digits anyway. If there are no fractional seconds,
-				 * then do not bother printing a decimal point at all. -
-				 * thomas 2001-09-29
-				 */
-				if (fsec != 0)
-				{
-					sprintf((str + strlen(str)), ":%013.10f", sec);
-					TrimTrailingZeros(str);
-				}
-				else
-					sprintf((str + strlen(str)), ":%02.0f", sec);
+			sprintf(str, "%04d-%02d-%02d %02d:%02d",
+					((tm->tm_year > 0)? tm->tm_year: -(tm->tm_year - 1)),
+					tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min);
 
-				/*
-				 * tzp == NULL indicates that we don't want *any* time
-				 * zone info in the output string. *tzn != NULL indicates
-				 * that we have alpha time zone info available. tm_isdst
-				 * != -1 indicates that we have a valid time zone
-				 * translation.
-				 */
-				if ((tzp != NULL) && (tm->tm_isdst >= 0))
-				{
-					hour = -(*tzp / 3600);
-					min = ((abs(*tzp) / 60) % 60);
-					sprintf((str + strlen(str)), ((min != 0) ? "%+03d:%02d" : "%+03d"), hour, min);
-				}
+			/*
+			 * If we have fractional seconds, then include a decimal
+			 * point We will do up to 6 fractional digits, and we have
+			 * rounded any inputs to eliminate anything to the right
+			 * of 6 digits anyway. If there are no fractional seconds,
+			 * then do not bother printing a decimal point at all. -
+			 * thomas 2001-09-29
+			 */
+#ifdef HAVE_INT64_TIMESTAMP
+			if (fsec != 0)
+			{
+				sprintf((str + strlen(str)), ":%02d", tm->tm_sec);
+				sprintf((str + strlen(str)), ".%06d", fsec);
+#else
+			if ((fsec != 0) && (tm->tm_year > 0))
+			{
+				sprintf((str + strlen(str)), ":%013.10f", sec);
+#endif
+				TrimTrailingZeros(str);
 			}
 			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");
+				sprintf((str + strlen(str)), ":%02d", tm->tm_sec);
+			}
+
+			if (tm->tm_year <= 0)
+			{
+				sprintf((str + strlen(str)), " BC");
+			}
+
+			/*
+			 * tzp == NULL indicates that we don't want *any* time
+			 * zone info in the output string.
+			 * *tzn != NULL indicates that we have alpha time zone
+			 * info available.
+			 * tm_isdst != -1 indicates that we have a valid time zone
+			 * translation.
+			 */
+			if ((tzp != NULL) && (tm->tm_isdst >= 0))
+			{
+				hour = -(*tzp / 3600);
+				min = ((abs(*tzp) / 60) % 60);
+				sprintf((str + strlen(str)), ((min != 0) ? "%+03d:%02d" : "%+03d"), hour, min);
 			}
 			break;
 
-			/* compatible with Oracle/Ingres date formats */
 		case USE_SQL_DATES:
+			/* Compatible with Oracle/Ingres date formats */
+
 			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",
+					((tm->tm_year > 0)? tm->tm_year: -(tm->tm_year - 1)),
+					tm->tm_hour, tm->tm_min);
+
+			/*
+			 * If we have fractional seconds, then include a decimal
+			 * point We will do up to 6 fractional digits, and we have
+			 * rounded any inputs to eliminate anything to the right
+			 * of 6 digits anyway. If there are no fractional seconds,
+			 * then do not bother printing a decimal point at all. -
+			 * thomas 2001-09-29
+			 */
+#ifdef HAVE_INT64_TIMESTAMP
+			if (fsec != 0)
+			{
+				sprintf((str + strlen(str)), ":%02d", tm->tm_sec);
+				sprintf((str + strlen(str)), ".%06d", fsec);
+#else
+			if ((fsec != 0) && (tm->tm_year > 0))
 			{
-				sprintf((str + 5), "/%04d %02d:%02d",
-						tm->tm_year, tm->tm_hour, tm->tm_min);
+				sprintf((str + strlen(str)), ":%013.10f", sec);
+#endif
+				TrimTrailingZeros(str);
+			}
+			else
+			{
+				sprintf((str + strlen(str)), ":%02d", tm->tm_sec);
+			}
 
-				/*
-				 * If we have fractional seconds, then include a decimal
-				 * point We will do up to 6 fractional digits, and we have
-				 * rounded any inputs to eliminate anything to the right
-				 * of 6 digits anyway. If there are no fractional seconds,
-				 * then do not bother printing a decimal point at all. -
-				 * thomas 2001-09-29
-				 */
-				if (fsec != 0)
-				{
-					sprintf((str + strlen(str)), ":%013.10f", sec);
-					TrimTrailingZeros(str);
-				}
-				else
-					sprintf((str + strlen(str)), ":%02.0f", sec);
+			if (tm->tm_year <= 0)
+			{
+				sprintf((str + strlen(str)), " BC");
+			}
 
-				if ((tzp != NULL) && (tm->tm_isdst >= 0))
+			if ((tzp != NULL) && (tm->tm_isdst >= 0))
+			{
+				if (*tzn != NULL)
+					sprintf((str + strlen(str)), " %.*s", MAXTZLEN, *tzn);
+				else
 				{
-					if (*tzn != NULL)
-						sprintf((str + strlen(str)), " %.*s", MAXTZLEN, *tzn);
-					else
-					{
-						hour = -(*tzp / 3600);
-						min = ((abs(*tzp) / 60) % 60);
-						sprintf((str + strlen(str)), ((min != 0) ? "%+03d:%02d" : "%+03d"), hour, min);
-					}
+					hour = -(*tzp / 3600);
+					min = ((abs(*tzp) / 60) % 60);
+					sprintf((str + strlen(str)), ((min != 0) ? "%+03d:%02d" : "%+03d"), hour, min);
 				}
 			}
-			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:
+			/* German variant on European style */
+
 			sprintf(str, "%02d.%02d", tm->tm_mday, tm->tm_mon);
-			if (tm->tm_year > 0)
+
+			sprintf((str + 5), ".%04d %02d:%02d",
+					((tm->tm_year > 0)? tm->tm_year: -(tm->tm_year - 1)),
+					tm->tm_hour, tm->tm_min);
+
+			/*
+			 * If we have fractional seconds, then include a decimal
+			 * point We will do up to 6 fractional digits, and we have
+			 * rounded any inputs to eliminate anything to the right
+			 * of 6 digits anyway. If there are no fractional seconds,
+			 * then do not bother printing a decimal point at all. -
+			 * thomas 2001-09-29
+			 */
+#ifdef HAVE_INT64_TIMESTAMP
+			if (fsec != 0)
+			{
+				sprintf((str + strlen(str)), ":%02d", tm->tm_sec);
+				sprintf((str + strlen(str)), ".%06d", fsec);
+#else
+			if ((fsec != 0) && (tm->tm_year > 0))
+			{
+				sprintf((str + strlen(str)), ":%013.10f", sec);
+#endif
+				TrimTrailingZeros(str);
+			}
+			else
 			{
-				sprintf((str + 5), ".%04d %02d:%02d",
-						tm->tm_year, tm->tm_hour, tm->tm_min);
+				sprintf((str + strlen(str)), ":%02d", tm->tm_sec);
+			}
 
-				/*
-				 * If we have fractional seconds, then include a decimal
-				 * point We will do up to 6 fractional digits, and we have
-				 * rounded any inputs to eliminate anything to the right
-				 * of 6 digits anyway. If there are no fractional seconds,
-				 * then do not bother printing a decimal point at all. -
-				 * thomas 2001-09-29
-				 */
-				if (fsec != 0)
-				{
-					sprintf((str + strlen(str)), ":%013.10f", sec);
-					TrimTrailingZeros(str);
-				}
-				else
-					sprintf((str + strlen(str)), ":%02.0f", sec);
+			if (tm->tm_year <= 0)
+			{
+				sprintf((str + strlen(str)), " BC");
+			}
 
-				if ((tzp != NULL) && (tm->tm_isdst >= 0))
+			if ((tzp != NULL) && (tm->tm_isdst >= 0))
+			{
+				if (*tzn != NULL)
+					sprintf((str + strlen(str)), " %.*s", MAXTZLEN, *tzn);
+				else
 				{
-					if (*tzn != NULL)
-						sprintf((str + strlen(str)), " %.*s", MAXTZLEN, *tzn);
-					else
-					{
-						hour = -(*tzp / 3600);
-						min = ((abs(*tzp) / 60) % 60);
-						sprintf((str + strlen(str)), ((min != 0) ? "%+03d:%02d" : "%+03d"), hour, min);
-					}
+					hour = -(*tzp / 3600);
+					min = ((abs(*tzp) / 60) % 60);
+					sprintf((str + strlen(str)), ((min != 0) ? "%+03d:%02d" : "%+03d"), hour, min);
 				}
 			}
-			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:
+			/* Backward-compatible with traditional Postgres abstime dates */
+
 			day = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday);
 			tm->tm_wday = j2day(day);
 
@@ -3117,52 +3281,58 @@ EncodeDateTime(struct tm * tm, double fsec, int *tzp, char **tzn, int style, cha
 			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);
+			sprintf((str + 10), " %02d:%02d", tm->tm_hour, tm->tm_min);
 
-				/*
-				 * If we have fractional seconds, then include a decimal
-				 * point We will do up to 6 fractional digits, and we have
-				 * rounded any inputs to eliminate anything to the right
-				 * of 6 digits anyway. If there are no fractional seconds,
-				 * then do not bother printing a decimal point at all. -
-				 * thomas 2001-09-29
-				 */
-				if (fsec != 0)
-				{
-					sprintf((str + strlen(str)), ":%013.10f", sec);
-					TrimTrailingZeros(str);
-				}
-				else
-					sprintf((str + strlen(str)), ":%02.0f", sec);
+			/*
+			 * If we have fractional seconds, then include a decimal
+			 * point We will do up to 6 fractional digits, and we have
+			 * rounded any inputs to eliminate anything to the right
+			 * of 6 digits anyway. If there are no fractional seconds,
+			 * then do not bother printing a decimal point at all. -
+			 * thomas 2001-09-29
+			 */
+#ifdef HAVE_INT64_TIMESTAMP
+			if (fsec != 0)
+			{
+				sprintf((str + strlen(str)), ":%02d", tm->tm_sec);
+				sprintf((str + strlen(str)), ".%06d", fsec);
+#else
+			if ((fsec != 0) && (tm->tm_year > 0))
+			{
+				sprintf((str + strlen(str)), ":%013.10f", sec);
+#endif
+				TrimTrailingZeros(str);
+			}
+			else
+			{
+				sprintf((str + strlen(str)), ":%02d", tm->tm_sec);
+			}
 
-				sprintf((str + strlen(str)), " %04d", tm->tm_year);
+			sprintf((str + strlen(str)), " %04d",
+					((tm->tm_year > 0)? tm->tm_year: -(tm->tm_year - 1)));
+			if (tm->tm_year <= 0)
+			{
+				sprintf((str + strlen(str)), " BC");
+			}
 
-				if ((tzp != NULL) && (tm->tm_isdst >= 0))
+			if ((tzp != NULL) && (tm->tm_isdst >= 0))
+			{
+				if (*tzn != NULL)
+					sprintf((str + strlen(str)), " %.*s", MAXTZLEN, *tzn);
+				else
 				{
-					if (*tzn != NULL)
-						sprintf((str + strlen(str)), " %.*s", MAXTZLEN, *tzn);
-					else
-					{
-						/*
-						 * We have a time zone, but no string version. Use
-						 * the numeric form, but be sure to include a
-						 * leading space to avoid formatting something
-						 * which would be rejected by the date/time parser
-						 * later. - thomas 2001-10-19
-						 */
-						hour = -(*tzp / 3600);
-						min = ((abs(*tzp) / 60) % 60);
-						sprintf((str + strlen(str)), ((min != 0) ? " %+03d:%02d" : " %+03d"), hour, min);
-					}
+					/*
+					 * We have a time zone, but no string version. Use
+					 * the numeric form, but be sure to include a
+					 * leading space to avoid formatting something
+					 * which would be rejected by the date/time parser
+					 * later. - thomas 2001-10-19
+					 */
+					hour = -(*tzp / 3600);
+					min = ((abs(*tzp) / 60) % 60);
+					sprintf((str + strlen(str)), ((min != 0) ? " %+03d:%02d" : " %+03d"), hour, min);
 				}
 			}
-			else
-			{
-				sprintf((str + 10), " %02d:%02d %04d %s",
-					  tm->tm_hour, tm->tm_min, -(tm->tm_year - 1), "BC");
-			}
 			break;
 	}
 
@@ -3170,7 +3340,7 @@ EncodeDateTime(struct tm * tm, double fsec, int *tzp, char **tzn, int style, cha
 }	/* EncodeDateTime() */
 
 
-/* EncodeTimeSpan()
+/* EncodeInterval()
  * Interpret time structure as a delta time and convert to string.
  *
  * Support "traditional Postgres" and ISO-8601 styles.
@@ -3179,7 +3349,7 @@ EncodeDateTime(struct tm * tm, double fsec, int *tzp, char **tzn, int style, cha
  * - thomas 1998-04-30
  */
 int
-EncodeTimeSpan(struct tm * tm, double fsec, int style, char *str)
+EncodeInterval(struct tm * tm, fsec_t fsec, int style, char *str)
 {
 	int			is_before = FALSE;
 	int			is_nonzero = FALSE;
@@ -3239,8 +3409,14 @@ EncodeTimeSpan(struct tm * tm, double fsec, int style, char *str)
 				/* fractional seconds? */
 				if (fsec != 0)
 				{
+#ifdef HAVE_INT64_TIMESTAMP
+					sprintf(cp, ":%02d", abs(tm->tm_sec));
+					cp += strlen(cp);
+					sprintf(cp, ".%06d", ((fsec >= 0)? fsec: -(fsec)));
+#else
 					fsec += tm->tm_sec;
 					sprintf(cp, ":%013.10f", fabs(fsec));
+#endif
 					TrimTrailingZeros(cp);
 					cp += strlen(cp);
 					is_nonzero = TRUE;
@@ -3336,7 +3512,16 @@ EncodeTimeSpan(struct tm * tm, double fsec, int style, char *str)
 			/* fractional seconds? */
 			if (fsec != 0)
 			{
-				double		sec;
+#ifdef HAVE_INT64_TIMESTAMP
+				if (is_before || ((!is_nonzero) && (tm->tm_sec < 0)))
+					tm->tm_sec = -tm->tm_sec;
+				sprintf(cp, "%s%d.%02d secs", (is_nonzero ? " " : ""),
+						tm->tm_sec, (((int) fsec) / 10000));
+				cp += strlen(cp);
+				if (!is_nonzero)
+					is_before = (fsec < 0);
+#else
+				fsec_t		sec;
 
 				fsec += tm->tm_sec;
 				sec = fsec;
@@ -3347,6 +3532,7 @@ EncodeTimeSpan(struct tm * tm, double fsec, int style, char *str)
 				cp += strlen(cp);
 				if (!is_nonzero)
 					is_before = (fsec < 0);
+#endif
 				is_nonzero = TRUE;
 
 				/* otherwise, integer seconds only? */
@@ -3382,7 +3568,7 @@ EncodeTimeSpan(struct tm * tm, double fsec, int style, char *str)
 	}
 
 	return 0;
-}	/* EncodeTimeSpan() */
+}	/* EncodeInterval() */
 
 
 void
diff --git a/src/backend/utils/adt/formatting.c b/src/backend/utils/adt/formatting.c
index 231bad2ca6dd2c976b9759b7d6edce148075bcde..7d28d16001f29aa80420b6a97aaa04e5bf951c0f 100644
--- a/src/backend/utils/adt/formatting.c
+++ b/src/backend/utils/adt/formatting.c
@@ -1,7 +1,7 @@
 /* -----------------------------------------------------------------------
  * formatting.c
  *
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/formatting.c,v 1.52 2002/04/03 05:39:29 petere Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/formatting.c,v 1.53 2002/04/21 19:48:12 thomas Exp $
  *
  *
  *	 Portions Copyright (c) 1999-2000, PostgreSQL Global Development Group
@@ -410,7 +410,7 @@ typedef struct
 typedef struct TmToChar
 {
 	struct tm	tm;				/* classic 'tm' struct */
-	double		fsec;			/* milliseconds */
+	fsec_t		fsec;			/* fractional seconds */
 	char	   *tzn;			/* timezone */
 } TmToChar;
 
@@ -1831,7 +1831,11 @@ dch_time(int arg, char *inout, int suf, int flag, FormatNode *node, void *data)
 		case DCH_MS:			/* millisecond */
 			if (flag == TO_CHAR)
 			{
+#ifdef HAVE_INT64_TIMESTAMP
+				sprintf(inout, "%03d", (int) (tmtc->fsec / INT64CONST(1000)));
+#else
 				sprintf(inout, "%03d", (int) rint(tmtc->fsec * 1000));
+#endif
 				if (S_THth(suf))
 					str_numth(p_inout, inout, S_TH_TYPE(suf));
 				if (S_THth(suf))
@@ -1874,7 +1878,11 @@ dch_time(int arg, char *inout, int suf, int flag, FormatNode *node, void *data)
 		case DCH_US:			/* microsecond */
 			if (flag == TO_CHAR)
 			{
+#ifdef HAVE_INT64_TIMESTAMP
+				sprintf(inout, "%06d", (int) tmtc->fsec);
+#else
 				sprintf(inout, "%06d", (int) rint(tmtc->fsec * 1000000));
+#endif
 				if (S_THth(suf))
 					str_numth(p_inout, inout, S_TH_TYPE(suf));
 				if (S_THth(suf))
@@ -2868,7 +2876,7 @@ to_timestamp(PG_FUNCTION_ARGS)
 				date_len,
 				tz = 0;
 	struct tm	tm;
-	double		fsec = 0;
+	fsec_t		fsec = 0;
 
 	ZERO_tm(&tm);
 	ZERO_tmfc(&tmfc);
@@ -3071,10 +3079,17 @@ to_timestamp(PG_FUNCTION_ARGS)
 				tm.tm_yday - y[i - 1];
 	}
 
+#ifdef HAVE_INT64_TIMESTAMP
+	if (tmfc.ms)
+		fsec += tmfc.ms * 1000;
+	if (tmfc.us)
+		fsec += tmfc.us;
+#else
 	if (tmfc.ms)
 		fsec += (double) tmfc.ms / 1000;
 	if (tmfc.us)
 		fsec += (double) tmfc.us / 1000000;
+#endif
 
 	/* -------------------------------------------------------------- */
 
diff --git a/src/backend/utils/adt/int8.c b/src/backend/utils/adt/int8.c
index 6a5eb15d749b5efaf76f366bcf52b0ebc719073d..685d5e34398aa19577d875bc9502b0ac61480990 100644
--- a/src/backend/utils/adt/int8.c
+++ b/src/backend/utils/adt/int8.c
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/int8.c,v 1.37 2002/02/23 01:01:30 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/int8.c,v 1.38 2002/04/21 19:48:12 thomas Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -23,6 +23,7 @@
 
 /* this should be set in pg_config.h, but just in case it wasn't: */
 #ifndef INT64_FORMAT
+#warning "Broken pg_config.h should have defined INT64_FORMAT"
 #define INT64_FORMAT "%ld"
 #endif
 
diff --git a/src/backend/utils/adt/nabstime.c b/src/backend/utils/adt/nabstime.c
index 299a082facb308e5ef0cd8baf80767576c0a7aca..651ca00d78ef2f33fa13508afbcc5fd4649bf297 100644
--- a/src/backend/utils/adt/nabstime.c
+++ b/src/backend/utils/adt/nabstime.c
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/nabstime.c,v 1.92 2002/03/06 06:10:13 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/nabstime.c,v 1.93 2002/04/21 19:48:12 thomas Exp $
  *
  * NOTES
  *
@@ -76,21 +76,6 @@
 				  AbsoluteTimeGetDatum(t1), \
 				  AbsoluteTimeGetDatum(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
@@ -98,12 +83,6 @@ static int	sec_tab[] = {
 
 static AbsoluteTime tm2abstime(struct tm * tm, int tz);
 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);
@@ -177,7 +156,7 @@ GetCurrentAbsoluteTime(void)
 }	/* GetCurrentAbsoluteTime() */
 
 
-/* GetCurrentAbsoluteTime()
+/* GetCurrentAbsoluteTimeUsec()
  * Get the current system time. Set timezone parameters if not specified elsewhere.
  * Define HasCTZSet to allow clients to specify the default timezone.
  *
@@ -271,13 +250,17 @@ GetCurrentTime(struct tm * tm)
 
 
 void
-GetCurrentTimeUsec(struct tm * tm, double *fsec)
+GetCurrentTimeUsec(struct tm * tm, fsec_t *fsec)
 {
 	int			tz;
 	int			usec;
 
 	abstime2tm(GetCurrentTransactionStartTimeUsec(&usec), &tz, tm, NULL);
+#ifdef HAVE_INT64_TIMESTAMP
+	*fsec = usec;
+#else
 	*fsec = usec * 1.0e-6;
+#endif
 
 	return;
 }	/* GetCurrentTimeUsec() */
@@ -493,7 +476,7 @@ nabstimein(PG_FUNCTION_ARGS)
 {
 	char	   *str = PG_GETARG_CSTRING(0);
 	AbsoluteTime result;
-	double		fsec;
+	fsec_t		fsec;
 	int			tz = 0;
 	struct tm	date,
 			   *tm = &date;
@@ -713,7 +696,7 @@ timestamp_abstime(PG_FUNCTION_ARGS)
 {
 	Timestamp	timestamp = PG_GETARG_TIMESTAMP(0);
 	AbsoluteTime result;
-	double		fsec;
+	fsec_t		fsec;
 	int			tz;
 	struct tm	tt,
 			   *tm = &tt;
@@ -767,7 +750,9 @@ abstime_timestamp(PG_FUNCTION_ARGS)
 
 		default:
 			abstime2tm(abstime, &tz, tm, &tzn);
-			result = abstime + ((date2j(1970, 1, 1) - date2j(2000, 1, 1)) * 86400) + tz;
+			if (tm2timestamp(tm, 0, NULL, &result) != 0)
+				elog(ERROR, "Unable convert ABSTIME to TIMESTAMP"
+					 "\n\tabstime_timestamp() internal error");
 			break;
 	};
 
@@ -783,7 +768,7 @@ timestamptz_abstime(PG_FUNCTION_ARGS)
 {
 	TimestampTz timestamp = PG_GETARG_TIMESTAMP(0);
 	AbsoluteTime result;
-	double		fsec;
+	fsec_t		fsec;
 	struct tm	tt,
 			   *tm = &tt;
 
@@ -810,6 +795,11 @@ abstime_timestamptz(PG_FUNCTION_ARGS)
 {
 	AbsoluteTime abstime = PG_GETARG_ABSOLUTETIME(0);
 	TimestampTz result;
+	struct tm	tt,
+			   *tm = &tt;
+	int			tz;
+	char		zone[MAXDATELEN + 1],
+			   *tzn = zone;
 
 	switch (abstime)
 	{
@@ -827,7 +817,10 @@ abstime_timestamptz(PG_FUNCTION_ARGS)
 			break;
 
 		default:
-			result = abstime + ((date2j(1970, 1, 1) - date2j(2000, 1, 1)) * 86400);
+			abstime2tm(abstime, &tz, tm, &tzn);
+			if (tm2timestamp(tm, 0, &tz, &result) != 0)
+				elog(ERROR, "Unable convert ABSTIME to TIMESTAMP WITH TIME ZONE"
+					 "\n\tabstime_timestamp() internal error");
 			break;
 	};
 
@@ -849,7 +842,7 @@ reltimein(PG_FUNCTION_ARGS)
 	RelativeTime result;
 	struct tm	tt,
 			   *tm = &tt;
-	double		fsec;
+	fsec_t		fsec;
 	int			dtype;
 	char	   *field[MAXDATEFIELDS];
 	int			nf,
@@ -860,14 +853,14 @@ reltimein(PG_FUNCTION_ARGS)
 		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))
+		|| (DecodeInterval(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));
+			result += ((tm->tm_year * 36525 * 864) + (((tm->tm_mon * 30) + tm->tm_mday) * 86400));
 			break;
 
 		default:
@@ -893,7 +886,7 @@ reltimeout(PG_FUNCTION_ARGS)
 	char		buf[MAXDATELEN + 1];
 
 	reltime2tm(time, tm);
-	EncodeTimeSpan(tm, 0, DateStyle, buf);
+	EncodeInterval(tm, 0, DateStyle, buf);
 
 	result = pstrdup(buf);
 	PG_RETURN_CSTRING(result);
@@ -903,7 +896,7 @@ reltimeout(PG_FUNCTION_ARGS)
 static void
 reltime2tm(RelativeTime time, struct tm * tm)
 {
-	TMODULO(time, tm->tm_year, 31536000);
+	TMODULO(time, tm->tm_year, 31557600);
 	TMODULO(time, tm->tm_mon, 2592000);
 	TMODULO(time, tm->tm_mday, 86400);
 	TMODULO(time, tm->tm_hour, 3600);
@@ -988,7 +981,11 @@ interval_reltime(PG_FUNCTION_ARGS)
 	RelativeTime time;
 	int			year,
 				month;
+#ifdef HAVE_INT64_TIMESTAMP
+	int64		span;
+#else
 	double		span;
+#endif
 
 	if (interval->month == 0)
 	{
@@ -1006,7 +1003,13 @@ interval_reltime(PG_FUNCTION_ARGS)
 		month = interval->month;
 	}
 
-	span = (((((double) 365 * year) + ((double) 30 * month)) * 86400) + interval->time);
+#ifdef HAVE_INT64_TIMESTAMP
+	span = ((((INT64CONST(365250000) * year) + (INT64CONST(30000000) * month))
+			 * INT64CONST(86400)) + interval->time);
+	span /= INT64CONST(1000000);
+#else
+	span = (((((double) 365.25 * year) + ((double) 30 * month)) * 86400) + interval->time);
+#endif
 
 	if ((span < INT_MIN) || (span > INT_MAX))
 		time = INVALID_RELTIME;
@@ -1036,10 +1039,19 @@ reltime_interval(PG_FUNCTION_ARGS)
 			break;
 
 		default:
-			TMODULO(reltime, year, 31536000);
-			TMODULO(reltime, month, 2592000);
+#ifdef HAVE_INT64_TIMESTAMP
+			year = (reltime / (36525 * 864));
+			reltime -= (year * (36525 * 864));
+			month = (reltime / (30 * 86400));
+			reltime -= (month * (30 * 86400));
+
+			result->time = (reltime * INT64CONST(1000000));
+#else
+			TMODULO(reltime, year, (36525 * 864));
+			TMODULO(reltime, month, (30 * 86400));
 
 			result->time = reltime;
+#endif
 			result->month = ((12 * year) + month);
 			break;
 	}
@@ -1090,11 +1102,6 @@ timepl(PG_FUNCTION_ARGS)
 	AbsoluteTime t1 = PG_GETARG_ABSOLUTETIME(0);
 	RelativeTime t2 = PG_GETARG_RELATIVETIME(1);
 
-#if 0
-	if (t1 == CURRENT_ABSTIME)
-		t1 = GetCurrentTransactionStartTime();
-#endif
-
 	if (AbsoluteTimeIsReal(t1) &&
 		RelativeTimeIsValid(t2) &&
 		((t2 > 0) ? (t1 < NOEND_ABSTIME - t2)
@@ -1114,11 +1121,6 @@ timemi(PG_FUNCTION_ARGS)
 	AbsoluteTime t1 = PG_GETARG_ABSOLUTETIME(0);
 	RelativeTime t2 = PG_GETARG_RELATIVETIME(1);
 
-#if 0
-	if (t1 == CURRENT_ABSTIME)
-		t1 = GetCurrentTransactionStartTime();
-#endif
-
 	if (AbsoluteTimeIsReal(t1) &&
 		RelativeTimeIsValid(t2) &&
 		((t2 > 0) ? (t1 > NOSTART_ABSTIME + t2)
diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c
index 3b1af8df5e180e4157b0c95c6ea80cbce91aa73e..d045705917dfbf857f8429ae476dd8366084f0a0 100644
--- a/src/backend/utils/adt/selfuncs.c
+++ b/src/backend/utils/adt/selfuncs.c
@@ -15,7 +15,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/selfuncs.c,v 1.108 2002/04/16 23:08:11 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/selfuncs.c,v 1.109 2002/04/21 19:48:13 thomas Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -2427,17 +2427,30 @@ convert_timevalue_to_scalar(Datum value, Oid typid)
 				 * assumed average month length of 365.25/12.0 days.  Not
 				 * too accurate, but plenty good enough for our purposes.
 				 */
+#ifdef HAVE_INT64_TIMESTAMP
+				return (interval->time + (interval->month * ((365.25 / 12.0) * 86400000000.0)));
+#else
 				return interval->time +
 					interval->month * (365.25 / 12.0 * 24.0 * 60.0 * 60.0);
+#endif
 			}
 		case RELTIMEOID:
+#ifdef HAVE_INT64_TIMESTAMP
+			return (DatumGetRelativeTime(value) * 1000000.0);
+#else
 			return DatumGetRelativeTime(value);
+#endif
 		case TINTERVALOID:
 			{
 				TimeInterval interval = DatumGetTimeInterval(value);
 
+#ifdef HAVE_INT64_TIMESTAMP
+				if (interval->status != 0)
+					return ((interval->data[1] - interval->data[0]) * 1000000.0);
+#else
 				if (interval->status != 0)
 					return interval->data[1] - interval->data[0];
+#endif
 				return 0;		/* for lack of a better idea */
 			}
 		case TIMEOID:
@@ -2447,7 +2460,11 @@ convert_timevalue_to_scalar(Datum value, Oid typid)
 				TimeTzADT  *timetz = DatumGetTimeTzADTP(value);
 
 				/* use GMT-equivalent time */
+#ifdef HAVE_INT64_TIMESTAMP
+				return (double) (timetz->time + (timetz->zone * 1000000.0));
+#else
 				return (double) (timetz->time + timetz->zone);
+#endif
 			}
 	}
 
diff --git a/src/backend/utils/adt/timestamp.c b/src/backend/utils/adt/timestamp.c
index 5fbdc5b8d89e57663448c7beb097159d00f2eaf1..7637ccf150b40de7f42e9b83b66e68cf4855e62a 100644
--- a/src/backend/utils/adt/timestamp.c
+++ b/src/backend/utils/adt/timestamp.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/timestamp.c,v 1.65 2002/03/09 17:35:36 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/timestamp.c,v 1.66 2002/04/21 19:48:13 thomas Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -29,7 +29,11 @@
 #include "utils/builtins.h"
 
 
-static double time2t(const int hour, const int min, const double sec);
+#ifdef HAVE_INT64_TIMESTAMP
+static int64 time2t(const int hour, const int min, const int sec, const fsec_t fsec);
+#else
+static double time2t(const int hour, const int min, const int sec, const fsec_t fsec);
+#endif
 static int	EncodeSpecialTimestamp(Timestamp dt, char *str);
 static Timestamp dt2local(Timestamp dt, int timezone);
 static void AdjustTimestampForTypmod(Timestamp *time, int32 typmod);
@@ -53,7 +57,7 @@ timestamp_in(PG_FUNCTION_ARGS)
 #endif
 	int32		typmod = PG_GETARG_INT32(2);
 	Timestamp	result;
-	double		fsec;
+	fsec_t		fsec;
 	struct tm	tt,
 			   *tm = &tt;
 	int			tz;
@@ -111,7 +115,7 @@ timestamp_out(PG_FUNCTION_ARGS)
 	char	   *result;
 	struct tm	tt,
 			   *tm = &tt;
-	double		fsec;
+	fsec_t		fsec;
 	char	   *tzn = NULL;
 	char		buf[MAXDATELEN + 1];
 
@@ -147,19 +151,81 @@ timestamp_scale(PG_FUNCTION_ARGS)
 static void
 AdjustTimestampForTypmod(Timestamp *time, int32 typmod)
 {
-	if (!TIMESTAMP_NOT_FINITE(*time) &&
-		(typmod >= 0) && (typmod <= 13))
+#ifdef HAVE_INT64_TIMESTAMP
+	static const int64 TimestampScales[MAX_TIMESTAMP_PRECISION+1] = {
+		INT64CONST(1000000),
+		INT64CONST(100000),
+		INT64CONST(10000),
+		INT64CONST(1000),
+		INT64CONST(100),
+		INT64CONST(10),
+		INT64CONST(1)
+	};
+
+	static const int64 TimestampOffsets[MAX_TIMESTAMP_PRECISION+1] = {
+		INT64CONST(-500000),
+		INT64CONST(-50000),
+		INT64CONST(-5000),
+		INT64CONST(-500),
+		INT64CONST(-50),
+		INT64CONST(-5),
+		INT64CONST(0)
+	};
+#else
+	static const double TimestampScales[MAX_TIMESTAMP_PRECISION+1] = {
+		1,
+		10,
+		100,
+		1000,
+		10000,
+		100000,
+		1000000
+	};
+
+	static const double TimestampOffsets[MAX_TIMESTAMP_PRECISION+1] = {
+		0.5,
+		0.05,
+		0.005,
+		0.0005,
+		0.00005,
+		0.000005,
+		0.0000005
+	};
+#endif
+
+	if (!TIMESTAMP_NOT_FINITE(*time)
+		&& (typmod != -1) && (typmod != MAX_TIMESTAMP_PRECISION))
 	{
-		static double TimestampScale = 1;
-		static int32 TimestampTypmod = 0;
+		if ((typmod < 0) || (typmod > MAX_TIMESTAMP_PRECISION))
+			elog(ERROR, "TIMESTAMP(%d) precision must be between %d and %d",
+				 typmod, 0, MAX_TIMESTAMP_PRECISION);
 
-		if (typmod != TimestampTypmod)
+#ifdef HAVE_INT64_TIMESTAMP
+		/* we have different truncation behavior depending on sign */
+		if (*time >= INT64CONST(0))
 		{
-			TimestampScale = pow(10.0, typmod);
-			TimestampTypmod = typmod;
+			*time = ((*time / TimestampScales[typmod])
+					 * TimestampScales[typmod]);
 		}
-
-		*time = (rint(((double) *time) * TimestampScale) / TimestampScale);
+		else
+		{
+			*time = (((*time + TimestampOffsets[typmod]) / TimestampScales[typmod])
+					 * TimestampScales[typmod]);
+		}
+#else
+		/* we have different truncation behavior depending on sign */
+		if (*time >= 0)
+		{
+			*time = (rint(((double) *time) * TimestampScales[typmod])
+					 / TimestampScales[typmod]);
+		}
+		else
+		{
+			/* Scale and truncate first, then add to help the rounding behavior */
+			*time = (rint((((double) *time) * TimestampScales[typmod]) + TimestampOffsets[typmod])
+					 / TimestampScales[typmod]);
+		}
+#endif
 	}
 }
 
@@ -177,7 +243,7 @@ timestamptz_in(PG_FUNCTION_ARGS)
 #endif
 	int32		typmod = PG_GETARG_INT32(2);
 	TimestampTz result;
-	double		fsec;
+	fsec_t		fsec;
 	struct tm	tt,
 			   *tm = &tt;
 	int			tz;
@@ -236,7 +302,7 @@ timestamptz_out(PG_FUNCTION_ARGS)
 	int			tz;
 	struct tm	tt,
 			   *tm = &tt;
-	double		fsec;
+	fsec_t		fsec;
 	char	   *tzn;
 	char		buf[MAXDATELEN + 1];
 
@@ -286,7 +352,7 @@ interval_in(PG_FUNCTION_ARGS)
 #endif
 	int32		typmod = PG_GETARG_INT32(2);
 	Interval   *result;
-	double		fsec;
+	fsec_t		fsec;
 	struct tm	tt,
 			   *tm = &tt;
 	int			dtype;
@@ -304,7 +370,7 @@ interval_in(PG_FUNCTION_ARGS)
 	fsec = 0;
 
 	if ((ParseDateTime(str, lowstr, field, ftype, MAXDATEFIELDS, &nf) != 0)
-		|| (DecodeDateDelta(field, ftype, nf, &dtype, tm, &fsec) != 0))
+		|| (DecodeInterval(field, ftype, nf, &dtype, tm, &fsec) != 0))
 		elog(ERROR, "Bad interval external representation '%s'", str);
 
 	result = (Interval *) palloc(sizeof(Interval));
@@ -338,13 +404,13 @@ interval_out(PG_FUNCTION_ARGS)
 	char	   *result;
 	struct tm	tt,
 			   *tm = &tt;
-	double		fsec;
+	fsec_t		fsec;
 	char		buf[MAXDATELEN + 1];
 
 	if (interval2tm(*span, tm, &fsec) != 0)
 		elog(ERROR, "Unable to encode interval; internal coding error");
 
-	if (EncodeTimeSpan(tm, fsec, DateStyle, buf) != 0)
+	if (EncodeInterval(tm, fsec, DateStyle, buf) != 0)
 		elog(ERROR, "Unable to format interval; internal coding error");
 
 	result = pstrdup(buf);
@@ -375,6 +441,48 @@ interval_scale(PG_FUNCTION_ARGS)
 static void
 AdjustIntervalForTypmod(Interval *interval, int32 typmod)
 {
+#ifdef HAVE_INT64_TIMESTAMP
+	static const int64 IntervalScales[MAX_INTERVAL_PRECISION+1] = {
+		INT64CONST(1000000),
+		INT64CONST(100000),
+		INT64CONST(10000),
+		INT64CONST(1000),
+		INT64CONST(100),
+		INT64CONST(10),
+		INT64CONST(1)
+	};
+
+	static const int64 IntervalOffsets[MAX_INTERVAL_PRECISION+1] = {
+		INT64CONST(-500000),
+		INT64CONST(-50000),
+		INT64CONST(-5000),
+		INT64CONST(-500),
+		INT64CONST(-50),
+		INT64CONST(-5),
+		INT64CONST(0)
+	};
+#else
+	static const double IntervalScales[MAX_INTERVAL_PRECISION+1] = {
+		1000000,
+		100000,
+		10000,
+		1000,
+		100,
+		10,
+		1
+	};
+
+	static const double IntervalOffsets[MAX_INTERVAL_PRECISION+1] = {
+		-500000,
+		-50000,
+		-5000,
+		-500,
+		-50,
+		-5,
+		0
+	};
+#endif
+
 	if (typmod != -1)
 	{
 		int			range = ((typmod >> 16) & 0x7FFF);
@@ -396,102 +504,190 @@ AdjustIntervalForTypmod(Interval *interval, int32 typmod)
 		}
 		/* YEAR TO MONTH */
 		else if (range == (MASK(YEAR) | MASK(MONTH)))
+		{
 			interval->time = 0;
+		}
 		else if (range == MASK(DAY))
 		{
 			interval->month = 0;
+#ifdef HAVE_INT64_TIMESTAMP
+			interval->time = (((int) (interval->time / INT64CONST(86400000000)))
+							  * INT64CONST(86400000000));
+#else
 			interval->time = (((int) (interval->time / 86400)) * 86400);
+#endif
 		}
 		else if (range == MASK(HOUR))
 		{
+#ifdef HAVE_INT64_TIMESTAMP
+			int64		day;
+#else
 			double		day;
+#endif
 
 			interval->month = 0;
+#ifdef HAVE_INT64_TIMESTAMP
+			day = (interval->time / INT64CONST(86400000000));
+			interval->time -= (day * INT64CONST(86400000000));
+			interval->time = ((interval->time / INT64CONST(3600000000))
+							  * INT64CONST(3600000000));
+#else
 			TMODULO(interval->time, day, 86400.0);
 			interval->time = (((int) (interval->time / 3600)) * 3600.0);
+#endif
 		}
 		else if (range == MASK(MINUTE))
 		{
+#ifdef HAVE_INT64_TIMESTAMP
+			int64		hour;
+#else
 			double		hour;
+#endif
 
 			interval->month = 0;
+#ifdef HAVE_INT64_TIMESTAMP
+			hour = (interval->time / INT64CONST(3600000000));
+			interval->time -= (hour * INT64CONST(3600000000));
+			interval->time = ((interval->time / INT64CONST(60000000))
+							  * INT64CONST(60000000));
+#else
 			TMODULO(interval->time, hour, 3600.0);
 			interval->time = (((int) (interval->time / 60)) * 60);
+#endif
 		}
 		else if (range == MASK(SECOND))
 		{
-			double		hour;
+#ifdef HAVE_INT64_TIMESTAMP
+			int64		minute;
+#else
+			double		minute;
+#endif
 
 			interval->month = 0;
-			TMODULO(interval->time, hour, 60.0);
+#ifdef HAVE_INT64_TIMESTAMP
+			minute = (interval->time / INT64CONST(60000000));
+			interval->time -= (minute * INT64CONST(60000000));
+#else
+			TMODULO(interval->time, minute, 60.0);
 /*			interval->time = (int)(interval->time); */
+#endif
 		}
 		/* DAY TO HOUR */
 		else if (range == (MASK(DAY) | MASK(HOUR)))
 		{
 			interval->month = 0;
+#ifdef HAVE_INT64_TIMESTAMP
+			interval->time = ((interval->time / INT64CONST(3600000000))
+							  * INT64CONST(3600000000));
+#else
 			interval->time = (((int) (interval->time / 3600)) * 3600);
+#endif
 		}
 		/* DAY TO MINUTE */
 		else if (range == (MASK(DAY) | MASK(HOUR) | MASK(MINUTE)))
 		{
 			interval->month = 0;
+#ifdef HAVE_INT64_TIMESTAMP
+			interval->time = ((interval->time / INT64CONST(60000000))
+							  * INT64CONST(60000000));
+#else
 			interval->time = (((int) (interval->time / 60)) * 60);
+#endif
 		}
 		/* DAY TO SECOND */
 		else if (range == (MASK(DAY) | MASK(HOUR) | MASK(MINUTE) | MASK(SECOND)))
+		{
 			interval->month = 0;
+		}
 		/* HOUR TO MINUTE */
 		else if (range == (MASK(HOUR) | MASK(MINUTE)))
 		{
+#ifdef HAVE_INT64_TIMESTAMP
+			int64		day;
+#else
 			double		day;
+#endif
 
 			interval->month = 0;
+#ifdef HAVE_INT64_TIMESTAMP
+			day = (interval->time / INT64CONST(86400000000));
+			interval->time -= (day * INT64CONST(86400000000));
+			interval->time = ((interval->time / INT64CONST(60000000))
+							  * INT64CONST(60000000));
+#else
 			TMODULO(interval->time, day, 86400.0);
 			interval->time = (((int) (interval->time / 60)) * 60);
+#endif
 		}
 		/* HOUR TO SECOND */
 		else if (range == (MASK(HOUR) | MASK(MINUTE) | MASK(SECOND)))
 		{
+#ifdef HAVE_INT64_TIMESTAMP
+			int64		day;
+#else
 			double		day;
+#endif
 
 			interval->month = 0;
+#ifdef HAVE_INT64_TIMESTAMP
+			day = (interval->time / INT64CONST(86400000000));
+			interval->time -= (day * INT64CONST(86400000000));
+#else
 			TMODULO(interval->time, day, 86400.0);
+#endif
 		}
 		/* MINUTE TO SECOND */
 		else if (range == (MASK(MINUTE) | MASK(SECOND)))
 		{
+#ifdef HAVE_INT64_TIMESTAMP
+			int64		hour;
+#else
 			double		hour;
+#endif
 
 			interval->month = 0;
+#ifdef HAVE_INT64_TIMESTAMP
+			hour = (interval->time / INT64CONST(3600000000));
+			interval->time -= (hour * INT64CONST(3600000000));
+#else
 			TMODULO(interval->time, hour, 3600.0);
+#endif
 		}
 		else
 			elog(ERROR, "AdjustIntervalForTypmod(): internal coding error");
 
+		/* Need to adjust precision? If not, don't even try! */
 		if (precision != 0xFFFF)
 		{
-			static double IntervalScale = 1;
-			static int	IntervalTypmod = 0;
+			if ((precision < 0) || (precision > MAX_INTERVAL_PRECISION))
+				elog(ERROR, "INTERVAL(%d) precision must be between %d and %d",
+					 precision, 0, MAX_INTERVAL_PRECISION);
 
-			if (precision != IntervalTypmod)
+#ifdef HAVE_INT64_TIMESTAMP
+			/* we have different truncation behavior depending on sign */
+			if (interval->time >= INT64CONST(0))
 			{
-				IntervalTypmod = precision;
-				IntervalScale = pow(10.0, IntervalTypmod);
+				interval->time = ((interval->time / IntervalScales[precision])
+								  * IntervalScales[precision]);
 			}
-
-			/*
-			 * Hmm. For the time field, we can get to a large value since
-			 * we store everything related to an absolute interval (e.g.
-			 * years worth of days) in this one field. So we have
-			 * precision problems doing rint() on this field if the field
-			 * is too large. This resulted in an annoying "...0001"
-			 * appended to the printed result on my Linux box. I hate
-			 * doing an expensive math operation like log10() to avoid
-			 * this, but what else can we do?? - thomas 2001-10-19
-			 */
-			if ((log10(interval->time) + IntervalTypmod) <= 13)
-				interval->time = (rint(interval->time * IntervalScale) / IntervalScale);
+			else
+			{
+				interval->time = (((interval->time + IntervalOffsets[precision]) / IntervalScales[precision])
+								  * IntervalScales[precision]);
+			}
+#else
+			/* we have different truncation behavior depending on sign */
+			if (interval->time >= 0)
+			{
+				interval->time = (rint(((double) interval->time) * IntervalScales[precision])
+								  / IntervalScales[precision]);
+			}
+			else
+			{
+				interval->time = (rint((((double) interval->time) + IntervalOffsets[precision])
+									   * IntervalScales[precision]) / IntervalScales[precision]);
+			}
+#endif
 		}
 	}
 
@@ -524,23 +720,42 @@ now(PG_FUNCTION_ARGS)
 
 	sec = GetCurrentTransactionStartTimeUsec(&usec);
 
+#ifdef HAVE_INT64_TIMESTAMP
+	result = (((sec - ((date2j(2000, 1, 1) - date2j(1970, 1, 1)) * 86400))
+			   * INT64CONST(1000000)) + usec);
+#else
 	result = (sec + (usec * 1.0e-6) - ((date2j(2000, 1, 1) - date2j(1970, 1, 1)) * 86400));
+#endif
 
 	PG_RETURN_TIMESTAMPTZ(result);
 }
 
 void
-dt2time(Timestamp jd, int *hour, int *min, double *sec)
+dt2time(Timestamp jd, int *hour, int *min, int *sec, fsec_t *fsec)
 {
+#ifdef HAVE_INT64_TIMESTAMP
+	int64		time;
+#else
 	double		time;
+#endif
 
 	time = jd;
 
+#ifdef HAVE_INT64_TIMESTAMP
+	*hour = (time / INT64CONST(3600000000));
+	time -= ((*hour) * INT64CONST(3600000000));
+	*min = (time / INT64CONST(60000000));
+	time -= ((*min) * INT64CONST(60000000));
+	*sec = (time / INT64CONST(1000000));
+	*fsec = (time - (*sec * INT64CONST(1000000)));
+#else
 	*hour = (time / 3600);
 	time -= ((*hour) * 3600);
 	*min = (time / 60);
 	time -= ((*min) * 60);
-	*sec = JROUND(time);
+	*sec = time;
+	*fsec = JROUND(time - *sec);
+#endif
 
 	return;
 }	/* dt2time() */
@@ -558,13 +773,18 @@ dt2time(Timestamp jd, int *hour, int *min, double *sec)
  *	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)
+timestamp2tm(Timestamp dt, int *tzp, struct tm *tm, fsec_t *fsec, char **tzn)
 {
-	double		date,
-				date0,
-				time,
-				sec;
-	time_t		utime;
+#ifdef HAVE_INT64_TIMESTAMP
+	int		date,
+			date0;
+	int64	time;
+#else
+	double	date,
+			date0;
+	double	time;
+#endif
+	time_t	utime;
 
 #if defined(HAVE_TM_ZONE) || defined(HAVE_INT_TIMEZONE)
 	struct tm  *tx;
@@ -578,9 +798,22 @@ timestamp2tm(Timestamp dt, int *tzp, struct tm * tm, double *fsec, char **tzn)
 	 * later bypass any calls which adjust the tm fields.
 	 */
 	if (HasCTZSet && (tzp != NULL))
+#ifdef HAVE_INT64_TIMESTAMP
+		dt -= (CTimeZone * INT64CONST(1000000));
+#else
 		dt -= CTimeZone;
+#endif
 
 	time = dt;
+#ifdef HAVE_INT64_TIMESTAMP
+	TMODULO(time, date, INT64CONST(86400000000));
+
+	if (time < INT64CONST(0))
+	{
+		time += INT64CONST(86400000000);
+		date -= 1;
+	}
+#else
 	TMODULO(time, date, 86400e0);
 
 	if (time < 0)
@@ -588,6 +821,7 @@ timestamp2tm(Timestamp dt, int *tzp, struct tm * tm, double *fsec, char **tzn)
 		time += 86400;
 		date -= 1;
 	}
+#endif
 
 	/* Julian day routine does not work for negative Julian days */
 	if (date < -date0)
@@ -597,10 +831,7 @@ timestamp2tm(Timestamp dt, int *tzp, struct tm * tm, double *fsec, char **tzn)
 	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);
+	dt2time(time, &tm->tm_hour, &tm->tm_min, &tm->tm_sec, fsec);
 
 	if (tzp != NULL)
 	{
@@ -626,7 +857,12 @@ timestamp2tm(Timestamp dt, int *tzp, struct tm * tm, double *fsec, char **tzn)
 		 */
 		else if (IS_VALID_UTIME(tm->tm_year, tm->tm_mon, tm->tm_mday))
 		{
-			utime = (dt + (date0 - date2j(1970, 1, 1)) * 86400);
+#ifdef HAVE_INT64_TIMESTAMP
+			utime = ((dt / INT64CONST(1000000))
+					 + ((date0 - date2j(1970, 1, 1)) * INT64CONST(86400)));
+#else
+			utime = (dt + ((date0 - date2j(1970, 1, 1)) * 86400));
+#endif
 
 #if defined(HAVE_TM_ZONE) || defined(HAVE_INT_TIMEZONE)
 			tx = localtime(&utime);
@@ -703,19 +939,27 @@ timestamp2tm(Timestamp dt, int *tzp, struct tm * tm, double *fsec, char **tzn)
  * Also, month is one-based, _not_ zero-based.
  */
 int
-tm2timestamp(struct tm * tm, double fsec, int *tzp, Timestamp *result)
+tm2timestamp(struct tm * tm, fsec_t fsec, int *tzp, Timestamp *result)
 {
-
+#ifdef HAVE_INT64_TIMESTAMP
+	int		date;
+	int64	time;
+#else
 	double		date,
 				time;
+#endif
 
 	/* 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);
+	time = time2t(tm->tm_hour, tm->tm_min, tm->tm_sec, fsec);
+#ifdef HAVE_INT64_TIMESTAMP
+	*result = ((date * INT64CONST(86400000000)) + time);
+#else
+	*result = ((date * 86400) + time);
+#endif
 	if (tzp != NULL)
 		*result = dt2local(*result, -(*tzp));
 
@@ -727,9 +971,13 @@ tm2timestamp(struct tm * tm, double fsec, int *tzp, Timestamp *result)
  * Convert a interval data type to a tm structure.
  */
 int
-interval2tm(Interval span, struct tm * tm, float8 *fsec)
+interval2tm(Interval span, struct tm * tm, fsec_t *fsec)
 {
+#ifdef HAVE_INT64_TIMESTAMP
+	int64		time;
+#else
 	double		time;
+#endif
 
 	if (span.month != 0)
 	{
@@ -743,45 +991,71 @@ interval2tm(Interval span, struct tm * tm, float8 *fsec)
 		tm->tm_mon = 0;
 	}
 
-#ifdef ROUND_ALL
-	time = JROUND(span.time);
-#else
 	time = span.time;
-#endif
 
+#ifdef HAVE_INT64_TIMESTAMP
+	tm->tm_mday = (time / INT64CONST(86400000000));
+	time -= (tm->tm_mday * INT64CONST(86400000000));
+	tm->tm_hour = (time / INT64CONST(3600000000));
+	time -= (tm->tm_hour * INT64CONST(3600000000));
+	tm->tm_min = (time / INT64CONST(60000000));
+	time -= (tm->tm_min * INT64CONST(60000000));
+	tm->tm_sec = (time / INT64CONST(1000000));
+	*fsec = (time - (tm->tm_sec * INT64CONST(1000000)));
+#else
 	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;
+#endif
 
 	return 0;
 }	/* interval2tm() */
 
 int
-tm2interval(struct tm * tm, double fsec, Interval *span)
+tm2interval(struct tm * tm, fsec_t fsec, Interval *span)
 {
 	span->month = ((tm->tm_year * 12) + tm->tm_mon);
+#ifdef HAVE_INT64_TIMESTAMP
+	span->time = ((((((((tm->tm_mday * INT64CONST(24))
+					  + tm->tm_hour) * INT64CONST(60))
+					+ tm->tm_min) * INT64CONST(60))
+				  + tm->tm_sec) * INT64CONST(1000000)) + fsec);
+#else
 	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);
+#endif
 
 	return 0;
 }	/* tm2interval() */
 
+#ifdef HAVE_INT64_TIMESTAMP
+static int64
+time2t(const int hour, const int min, const int sec, const fsec_t fsec)
+{
+	return ((((((hour * 60) + min) * 60) + sec) * INT64CONST(1000000)) + fsec);
+}	/* time2t() */
+#else
 static double
-time2t(const int hour, const int min, const double sec)
+time2t(const int hour, const int min, const int sec, const fsec_t fsec)
 {
-	return (((hour * 60) + min) * 60) + sec;
+	return ((((hour * 60) + min) * 60) + sec + fsec);
 }	/* time2t() */
+#endif
 
 static Timestamp
 dt2local(Timestamp dt, int tz)
 {
+#ifdef HAVE_INT64_TIMESTAMP
+	dt -= (tz * INT64CONST(1000000));
+#else
 	dt -= tz;
 	dt = JROUND(dt);
+#endif
 	return dt;
 }	/* dt2local() */
 
@@ -928,15 +1202,28 @@ timestamp_cmp(PG_FUNCTION_ARGS)
 static int
 interval_cmp_internal(Interval *interval1, Interval *interval2)
 {
+#ifdef HAVE_INT64_TIMESTAMP
+	int64		span1,
+				span2;
+#else
 	double		span1,
 				span2;
+#endif
 
 	span1 = interval1->time;
+	span2 = interval2->time;
+
+#ifdef HAVE_INT64_TIMESTAMP
+	if (interval1->month != 0)
+		span1 += ((interval1->month * INT64CONST(30) * INT64CONST(86400000000)));
+	if (interval2->month != 0)
+		span2 += ((interval2->month * INT64CONST(30) * INT64CONST(86400000000)));
+#else
 	if (interval1->month != 0)
 		span1 += (interval1->month * (30.0 * 86400));
-	span2 = interval2->time;
 	if (interval2->month != 0)
 		span2 += (interval2->month * (30.0 * 86400));
+#endif
 
 	return ((span1 < span2) ? -1 : (span1 > span2) ? 1 : 0);
 }
@@ -1017,7 +1304,7 @@ interval_hash(PG_FUNCTION_ARGS)
 	 * sizeof(Interval), so that any garbage pad bytes in the structure
 	 * won't be included in the hash!
 	 */
-	return hash_any((unsigned char *) key, sizeof(double) + sizeof(int4));
+	return hash_any((unsigned char *) key, sizeof(key->time) + sizeof(key->month));
 }
 
 /* overlaps_timestamp() --- implements the SQL92 OVERLAPS operator.
@@ -1195,7 +1482,11 @@ timestamp_mi(PG_FUNCTION_ARGS)
 		result->time = 0;
 	}
 	else
+#ifdef HAVE_INT64_TIMESTAMP
+		result->time = (dt1 - dt2);
+#else
 		result->time = JROUND(dt1 - dt2);
+#endif
 
 	result->month = 0;
 
@@ -1220,14 +1511,16 @@ timestamp_pl_span(PG_FUNCTION_ARGS)
 	Timestamp	result;
 
 	if (TIMESTAMP_NOT_FINITE(timestamp))
+	{
 		result = timestamp;
+	}
 	else
 	{
 		if (span->month != 0)
 		{
 			struct tm	tt,
 					   *tm = &tt;
-			double		fsec;
+			fsec_t		fsec;
 
 			if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL) == 0)
 			{
@@ -1262,12 +1555,7 @@ timestamp_pl_span(PG_FUNCTION_ARGS)
 			}
 		}
 
-#ifdef ROUND_ALL
-		timestamp = JROUND(timestamp + span->time);
-#else
 		timestamp += span->time;
-#endif
-
 		result = timestamp;
 	}
 
@@ -1316,7 +1604,7 @@ timestamptz_pl_span(PG_FUNCTION_ARGS)
 		{
 			struct tm	tt,
 					   *tm = &tt;
-			double		fsec;
+			fsec_t		fsec;
 
 			if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn) == 0)
 			{
@@ -1349,12 +1637,7 @@ timestamptz_pl_span(PG_FUNCTION_ARGS)
 			}
 		}
 
-#ifdef ROUND_ALL
-		timestamp = JROUND(timestamp + span->time);
-#else
 		timestamp += span->time;
-#endif
-
 		result = timestamp;
 	}
 
@@ -1398,17 +1681,29 @@ interval_smaller(PG_FUNCTION_ARGS)
 	Interval   *interval1 = PG_GETARG_INTERVAL_P(0);
 	Interval   *interval2 = PG_GETARG_INTERVAL_P(1);
 	Interval   *result;
+#ifdef HAVE_INT64_TIMESTAMP
+	int64		span1,
+				span2;
+#else
 	double		span1,
 				span2;
+#endif
 
 	result = (Interval *) palloc(sizeof(Interval));
 
 	span1 = interval1->time;
+	span2 = interval2->time;
+#ifdef HAVE_INT64_TIMESTAMP
+	if (interval1->month != 0)
+		span1 += ((interval1->month * INT64CONST(30) * INT64CONST(86400000000)));
+	if (interval2->month != 0)
+		span2 += ((interval2->month * INT64CONST(30) * INT64CONST(86400000000)));
+#else
 	if (interval1->month != 0)
 		span1 += (interval1->month * (30.0 * 86400));
-	span2 = interval2->time;
 	if (interval2->month != 0)
 		span2 += (interval2->month * (30.0 * 86400));
+#endif
 
 	if (span2 < span1)
 	{
@@ -1430,17 +1725,29 @@ interval_larger(PG_FUNCTION_ARGS)
 	Interval   *interval1 = PG_GETARG_INTERVAL_P(0);
 	Interval   *interval2 = PG_GETARG_INTERVAL_P(1);
 	Interval   *result;
+#ifdef HAVE_INT64_TIMESTAMP
+	int64		span1,
+				span2;
+#else
 	double		span1,
 				span2;
+#endif
 
 	result = (Interval *) palloc(sizeof(Interval));
 
 	span1 = interval1->time;
+	span2 = interval2->time;
+#ifdef HAVE_INT64_TIMESTAMP
+	if (interval1->month != 0)
+		span1 += ((interval1->month * INT64CONST(30) * INT64CONST(86400000000)));
+	if (interval2->month != 0)
+		span2 += ((interval2->month * INT64CONST(30) * INT64CONST(86400000000)));
+#else
 	if (interval1->month != 0)
 		span1 += (interval1->month * (30.0 * 86400));
-	span2 = interval2->time;
 	if (interval2->month != 0)
 		span2 += (interval2->month * (30.0 * 86400));
+#endif
 
 	if (span2 > span1)
 	{
@@ -1466,7 +1773,11 @@ interval_pl(PG_FUNCTION_ARGS)
 	result = (Interval *) palloc(sizeof(Interval));
 
 	result->month = (span1->month + span2->month);
+#ifdef HAVE_INT64_TIMESTAMP
+	result->time = (span1->time + span2->time);
+#else
 	result->time = JROUND(span1->time + span2->time);
+#endif
 
 	PG_RETURN_INTERVAL_P(result);
 }
@@ -1481,7 +1792,11 @@ interval_mi(PG_FUNCTION_ARGS)
 	result = (Interval *) palloc(sizeof(Interval));
 
 	result->month = (span1->month - span2->month);
+#ifdef HAVE_INT64_TIMESTAMP
+	result->time = (span1->time - span2->time);
+#else
 	result->time = JROUND(span1->time - span2->time);
+#endif
 
 	PG_RETURN_INTERVAL_P(result);
 }
@@ -1492,15 +1807,26 @@ interval_mul(PG_FUNCTION_ARGS)
 	Interval   *span1 = PG_GETARG_INTERVAL_P(0);
 	float8		factor = PG_GETARG_FLOAT8(1);
 	Interval   *result;
+#ifdef HAVE_INT64_TIMESTAMP
+	int64		months;
+#else
 	double		months;
+#endif
 
 	result = (Interval *) palloc(sizeof(Interval));
 
 	months = (span1->month * factor);
+#ifdef HAVE_INT64_TIMESTAMP
+	result->month = months;
+	result->time = (span1->time * factor);
+	result->time += ((months - result->month) * INT64CONST(30)
+					 * INT64CONST(86400000000));
+#else
 	result->month = rint(months);
 	result->time = JROUND(span1->time * factor);
 	/* evaluate fractional months as 30 days */
 	result->time += JROUND((months - result->month) * 30 * 86400);
+#endif
 
 	PG_RETURN_INTERVAL_P(result);
 }
@@ -1518,21 +1844,31 @@ mul_d_interval(PG_FUNCTION_ARGS)
 Datum
 interval_div(PG_FUNCTION_ARGS)
 {
-	Interval   *span1 = PG_GETARG_INTERVAL_P(0);
+	Interval   *span = PG_GETARG_INTERVAL_P(0);
 	float8		factor = PG_GETARG_FLOAT8(1);
 	Interval   *result;
+#ifndef HAVE_INT64_TIMESTAMP
 	double		months;
+#endif
 
 	result = (Interval *) palloc(sizeof(Interval));
 
 	if (factor == 0.0)
 		elog(ERROR, "interval_div: divide by 0.0 error");
 
-	months = (span1->month / factor);
+#ifdef HAVE_INT64_TIMESTAMP
+	result->month = (span->month / factor);
+	result->time = (span->time / factor);
+	/* evaluate fractional months as 30 days */
+	result->time += (((span->month - (result->month * factor))
+					  * INT64CONST(30) * INT64CONST(86400000000)) / factor);
+#else
+	months = (span->month / factor);
 	result->month = rint(months);
-	result->time = JROUND(span1->time / factor);
+	result->time = JROUND(span->time / factor);
 	/* evaluate fractional months as 30 days */
 	result->time += JROUND((months - result->month) * 30 * 86400);
+#endif
 
 	PG_RETURN_INTERVAL_P(result);
 }
@@ -1641,7 +1977,7 @@ timestamp_age(PG_FUNCTION_ARGS)
 	Timestamp	dt1 = PG_GETARG_TIMESTAMP(0);
 	Timestamp	dt2 = PG_GETARG_TIMESTAMP(1);
 	Interval   *result;
-	double		fsec,
+	fsec_t		fsec,
 				fsec1,
 				fsec2;
 	struct tm	tt,
@@ -1750,7 +2086,7 @@ timestamptz_age(PG_FUNCTION_ARGS)
 	TimestampTz dt1 = PG_GETARG_TIMESTAMP(0);
 	TimestampTz dt2 = PG_GETARG_TIMESTAMP(1);
 	Interval   *result;
-	double		fsec,
+	fsec_t		fsec,
 				fsec1,
 				fsec2;
 	struct tm	tt,
@@ -2033,7 +2369,7 @@ timestamp_trunc(PG_FUNCTION_ARGS)
 	char	   *up,
 			   *lp,
 				lowunits[MAXDATELEN + 1];
-	double		fsec;
+	fsec_t		fsec;
 	struct tm	tt,
 			   *tm = &tt;
 
@@ -2079,11 +2415,17 @@ timestamp_trunc(PG_FUNCTION_ARGS)
 				break;
 
 			case DTK_MILLISEC:
+#ifdef HAVE_INT64_TIMESTAMP
+				fsec = ((fsec / 1000) * 1000);
+#else
 				fsec = rint(fsec * 1000) / 1000;
+#endif
 				break;
 
 			case DTK_MICROSEC:
+#ifndef HAVE_INT64_TIMESTAMP
 				fsec = rint(fsec * 1000000) / 1000000;
+#endif
 				break;
 
 			default:
@@ -2119,7 +2461,7 @@ timestamptz_trunc(PG_FUNCTION_ARGS)
 	char	   *up,
 			   *lp,
 				lowunits[MAXDATELEN + 1];
-	double		fsec;
+	fsec_t		fsec;
 	char	   *tzn;
 	struct tm	tt,
 			   *tm = &tt;
@@ -2166,10 +2508,16 @@ timestamptz_trunc(PG_FUNCTION_ARGS)
 				break;
 
 			case DTK_MILLISEC:
+#ifdef HAVE_INT64_TIMESTAMP
+				fsec = ((fsec / 1000) * 1000);
+#else
 				fsec = rint(fsec * 1000) / 1000;
+#endif
 				break;
 			case DTK_MICROSEC:
+#ifndef HAVE_INT64_TIMESTAMP
 				fsec = rint(fsec * 1000000) / 1000000;
+#endif
 				break;
 
 			default:
@@ -2206,7 +2554,7 @@ interval_trunc(PG_FUNCTION_ARGS)
 	char	   *up,
 			   *lp,
 				lowunits[MAXDATELEN + 1];
-	double		fsec;
+	fsec_t		fsec;
 	struct tm	tt,
 			   *tm = &tt;
 
@@ -2253,11 +2601,16 @@ interval_trunc(PG_FUNCTION_ARGS)
 					break;
 
 				case DTK_MILLISEC:
+#ifdef HAVE_INT64_TIMESTAMP
+					fsec = ((fsec / 1000) * 1000);
+#else
 					fsec = rint(fsec * 1000) / 1000;
+#endif
 					break;
-
 				case DTK_MICROSEC:
+#ifndef HAVE_INT64_TIMESTAMP
 					fsec = rint(fsec * 1000000) / 1000000;
+#endif
 					break;
 
 				default:
@@ -2380,7 +2733,7 @@ timestamp_part(PG_FUNCTION_ARGS)
 	char	   *up,
 			   *lp,
 				lowunits[MAXDATELEN + 1];
-	double		fsec;
+	fsec_t		fsec;
 	struct tm	tt,
 			   *tm = &tt;
 
@@ -2410,15 +2763,27 @@ timestamp_part(PG_FUNCTION_ARGS)
 		switch (val)
 		{
 			case DTK_MICROSEC:
+#ifdef HAVE_INT64_TIMESTAMP
+				result = ((tm->tm_sec * 1000000e0) + fsec);
+#else
 				result = (tm->tm_sec + fsec) * 1000000;
+#endif
 				break;
 
 			case DTK_MILLISEC:
+#ifdef HAVE_INT64_TIMESTAMP
+				result = ((tm->tm_sec * 1000e0) + (fsec / 1000e0));
+#else
 				result = (tm->tm_sec + fsec) * 1000;
+#endif
 				break;
 
 			case DTK_SECOND:
+#ifdef HAVE_INT64_TIMESTAMP
+				result = (tm->tm_sec + (fsec / 1000000e0));
+#else
 				result = (tm->tm_sec + fsec);
+#endif
 				break;
 
 			case DTK_MINUTE:
@@ -2463,7 +2828,13 @@ timestamp_part(PG_FUNCTION_ARGS)
 
 			case DTK_JULIAN:
 				result = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday);
-				result += (((((tm->tm_hour * 60) + tm->tm_min) * 60) + tm->tm_sec) / 86400e0);
+#ifdef HAVE_INT64_TIMESTAMP
+				result += (((((tm->tm_hour * 60) + tm->tm_min) * 60)
+							+ tm->tm_sec + (fsec / 1000000e0)) / 86400e0);
+#else
+				result += (((((tm->tm_hour * 60) + tm->tm_min) * 60)
+							+ tm->tm_sec + fsec) / 86400e0);
+#endif
 				break;
 
 			case DTK_TZ:
@@ -2479,7 +2850,7 @@ timestamp_part(PG_FUNCTION_ARGS)
 		switch (val)
 		{
 			case DTK_EPOCH:
-				result = timestamp - SetEpochTimestamp();
+				result = ((timestamp - SetEpochTimestamp()) / 1000000e0);
 				break;
 
 			case DTK_DOW:
@@ -2529,7 +2900,7 @@ timestamptz_part(PG_FUNCTION_ARGS)
 			   *lp,
 				lowunits[MAXDATELEN + 1];
 	double		dummy;
-	double		fsec;
+	fsec_t		fsec;
 	char	   *tzn;
 	struct tm	tt,
 			   *tm = &tt;
@@ -2574,15 +2945,27 @@ timestamptz_part(PG_FUNCTION_ARGS)
 				break;
 
 			case DTK_MICROSEC:
+#ifdef HAVE_INT64_TIMESTAMP
+				result = ((tm->tm_sec * 1000000e0) + fsec);
+#else
 				result = (tm->tm_sec + fsec) * 1000000;
+#endif
 				break;
 
 			case DTK_MILLISEC:
+#ifdef HAVE_INT64_TIMESTAMP
+				result = ((tm->tm_sec * 1000e0) + (fsec / 1000e0));
+#else
 				result = (tm->tm_sec + fsec) * 1000;
+#endif
 				break;
 
 			case DTK_SECOND:
+#ifdef HAVE_INT64_TIMESTAMP
+				result = (tm->tm_sec + (fsec / 1000000e0));
+#else
 				result = (tm->tm_sec + fsec);
+#endif
 				break;
 
 			case DTK_MINUTE:
@@ -2627,7 +3010,13 @@ timestamptz_part(PG_FUNCTION_ARGS)
 
 			case DTK_JULIAN:
 				result = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday);
-				result += (((((tm->tm_hour * 60) + tm->tm_min) * 60) + tm->tm_sec) / 86400e0);
+#ifdef HAVE_INT64_TIMESTAMP
+				result += (((((tm->tm_hour * 60) + tm->tm_min) * 60)
+							+ tm->tm_sec + (fsec / 1000000e0)) / 86400e0);
+#else
+				result += (((((tm->tm_hour * 60) + tm->tm_min) * 60)
+							+ tm->tm_sec + fsec) / 86400e0);
+#endif
 				break;
 
 			default:
@@ -2641,7 +3030,11 @@ timestamptz_part(PG_FUNCTION_ARGS)
 		switch (val)
 		{
 			case DTK_EPOCH:
+#ifdef HAVE_INT64_TIMESTAMP
+				result = ((timestamp - SetEpochTimestamp()) / 100000e0);
+#else
 				result = timestamp - SetEpochTimestamp();
+#endif
 				break;
 
 			case DTK_DOW:
@@ -2689,7 +3082,7 @@ interval_part(PG_FUNCTION_ARGS)
 	char	   *up,
 			   *lp,
 				lowunits[MAXDATELEN + 1];
-	double		fsec;
+	fsec_t		fsec;
 	struct tm	tt,
 			   *tm = &tt;
 
@@ -2713,17 +3106,29 @@ interval_part(PG_FUNCTION_ARGS)
 		{
 			switch (val)
 			{
-				case DTK_MICROSEC:
-					result = ((tm->tm_sec + fsec) * 1000000);
-					break;
+			case DTK_MICROSEC:
+#ifdef HAVE_INT64_TIMESTAMP
+				result = ((tm->tm_sec * 1000000e0) + fsec);
+#else
+				result = (tm->tm_sec + fsec) * 1000000;
+#endif
+				break;
 
-				case DTK_MILLISEC:
-					result = ((tm->tm_sec + fsec) * 1000);
-					break;
+			case DTK_MILLISEC:
+#ifdef HAVE_INT64_TIMESTAMP
+				result = ((tm->tm_sec * 1000e0) + (fsec / 1000e0));
+#else
+				result = (tm->tm_sec + fsec) * 1000;
+#endif
+				break;
 
-				case DTK_SECOND:
-					result = (tm->tm_sec + fsec);
-					break;
+			case DTK_SECOND:
+#ifdef HAVE_INT64_TIMESTAMP
+				result = (tm->tm_sec + (fsec / 1000000e0));
+#else
+				result = (tm->tm_sec + fsec);
+#endif
+				break;
 
 				case DTK_MINUTE:
 					result = tm->tm_min;
@@ -2778,11 +3183,15 @@ interval_part(PG_FUNCTION_ARGS)
 	}
 	else if ((type == RESERV) && (val == DTK_EPOCH))
 	{
+#ifdef HAVE_INT64_TIMESTAMP
+		result = (interval->time / 1000000e0);
+#else
 		result = interval->time;
+#endif
 		if (interval->month != 0)
 		{
 			result += ((365.25 * 86400) * (interval->month / 12));
-			result += ((30 * 86400) * (interval->month % 12));
+			result += ((30.0 * 86400) * (interval->month % 12));
 		}
 	}
 	else
@@ -2799,6 +3208,8 @@ interval_part(PG_FUNCTION_ARGS)
 
 /* timestamp_zone()
  * Encode timestamp type with specified time zone.
+ * Returns timestamp with time zone, with the input
+ *  rotated from local time to the specified zone.
  */
 Datum
 timestamp_zone(PG_FUNCTION_ARGS)
@@ -2832,8 +3243,9 @@ timestamp_zone(PG_FUNCTION_ARGS)
 
 	if ((type == TZ) || (type == DTZ))
 	{
-		tz = val * 60;
-		result = timestamp - tz;
+		tz = -(val * 60);
+
+		result = dt2local(timestamp, tz);
 	}
 	else
 	{
@@ -2846,7 +3258,6 @@ timestamp_zone(PG_FUNCTION_ARGS)
 
 /* timestamp_izone()
  * Encode timestamp type with specified time interval as time zone.
- * Require ISO-formatted result, since character-string time zone is not available.
  */
 Datum
 timestamp_izone(PG_FUNCTION_ARGS)
@@ -2864,8 +3275,13 @@ timestamp_izone(PG_FUNCTION_ARGS)
 			 DatumGetCString(DirectFunctionCall1(interval_out,
 												 PointerGetDatum(zone))));
 
-	tz = -(zone->time);
-	result = timestamp - tz;
+#ifdef HAVE_INT64_TIMESTAMP
+	tz = (zone->time / INT64CONST(1000000));
+#else
+	tz = (zone->time);
+#endif
+
+	result = dt2local(timestamp, tz);
 
 	PG_RETURN_TIMESTAMPTZ(result);
 }	/* timestamp_izone() */
@@ -2880,7 +3296,7 @@ timestamp_timestamptz(PG_FUNCTION_ARGS)
 	TimestampTz result;
 	struct tm	tt,
 			   *tm = &tt;
-	double		fsec;
+	fsec_t		fsec;
 	int			tz;
 
 	if (TIMESTAMP_NOT_FINITE(timestamp))
@@ -2909,7 +3325,7 @@ timestamptz_timestamp(PG_FUNCTION_ARGS)
 	Timestamp	result;
 	struct tm	tt,
 			   *tm = &tt;
-	double		fsec;
+	fsec_t		fsec;
 	char	   *tzn;
 	int			tz;
 
@@ -2928,15 +3344,16 @@ timestamptz_timestamp(PG_FUNCTION_ARGS)
 }
 
 /* timestamptz_zone()
- * Encode timestamp with time zone type with specified time zone.
+ * Evaluate timestamp with time zone type at the specified time zone.
+ * Returns a timestamp without time zone.
  */
 Datum
 timestamptz_zone(PG_FUNCTION_ARGS)
 {
 	text	   *zone = PG_GETARG_TEXT_P(0);
 	TimestampTz timestamp = PG_GETARG_TIMESTAMP(1);
-	text	   *result;
-	TimestampTz dt;
+	Timestamp	result;
+
 	int			tz;
 	int			type,
 				val;
@@ -2944,13 +3361,6 @@ timestamptz_zone(PG_FUNCTION_ARGS)
 	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 (VARSIZE(zone) - VARHDRSZ > MAXDATELEN)
 		elog(ERROR, "Time zone '%s' not recognized",
@@ -2965,86 +3375,50 @@ timestamptz_zone(PG_FUNCTION_ARGS)
 	type = DecodeSpecial(0, lowzone, &val);
 
 	if (TIMESTAMP_NOT_FINITE(timestamp))
-		PG_RETURN_TEXT_P(pstrdup(""));
+		PG_RETURN_NULL();
 
 	if ((type == TZ) || (type == DTZ))
 	{
-		tm->tm_isdst = ((type == DTZ) ? 1 : 0);
 		tz = val * 60;
 
-		dt = dt2local(timestamp, tz);
-
-		if (timestamp2tm(dt, NULL, tm, &fsec, NULL) != 0)
-			elog(ERROR, "Unable to decode TIMESTAMP WITH TIME ZONE"
-				 "\n\ttimestamptz_zone() internal coding error");
-
-		up = upzone;
-		lp = lowzone;
-		for (i = 0; *lp != '\0'; i++)
-			*up++ = toupper((unsigned char) *lp++);
-		*up = '\0';
-
-		tzn = upzone;
-		EncodeDateTime(tm, fsec, &tz, &tzn, DateStyle, buf);
-
-		len = (strlen(buf) + VARHDRSZ);
-
-		result = palloc(len);
-
-		VARATT_SIZEP(result) = len;
-		memmove(VARDATA(result), buf, (len - VARHDRSZ));
+		result = dt2local(timestamp, tz);
 	}
 	else
 	{
 		elog(ERROR, "Time zone '%s' not recognized", lowzone);
-		PG_RETURN_TEXT_P(pstrdup(""));
+		PG_RETURN_NULL();
 	}
 
-	PG_RETURN_TEXT_P(result);
+	PG_RETURN_TIMESTAMP(result);
 }	/* timestamptz_zone() */
 
 /* timestamptz_izone()
  * Encode timestamp with time zone type with specified time interval as time zone.
- * Require ISO-formatted result, since character-string time zone is not available.
+ * Returns a timestamp without time zone.
  */
 Datum
 timestamptz_izone(PG_FUNCTION_ARGS)
 {
 	Interval   *zone = PG_GETARG_INTERVAL_P(0);
 	TimestampTz timestamp = PG_GETARG_TIMESTAMP(1);
-	text	   *result;
-	TimestampTz dt;
+	Timestamp	result;
 	int			tz;
-	char	   *tzn = "";
-	double		fsec;
-	struct tm	tt,
-			   *tm = &tt;
-	char		buf[MAXDATELEN + 1];
-	int			len;
 
 	if (TIMESTAMP_NOT_FINITE(timestamp))
-		PG_RETURN_TEXT_P(pstrdup(""));
+		PG_RETURN_NULL();
 
 	if (zone->month != 0)
 		elog(ERROR, "INTERVAL time zone '%s' not legal (month specified)",
 			 DatumGetCString(DirectFunctionCall1(interval_out,
 												 PointerGetDatum(zone))));
 
-	tm->tm_isdst = -1;
+#ifdef HAVE_INT64_TIMESTAMP
+	tz = -(zone->time / INT64CONST(1000000));
+#else
 	tz = -(zone->time);
+#endif
 
-	dt = dt2local(timestamp, tz);
-
-	if (timestamp2tm(dt, NULL, tm, &fsec, NULL) != 0)
-		elog(ERROR, "Unable to decode TIMESTAMP WITH TIME ZONE"
-			 "\n\ttimestamptz_izone() internal coding error");
-
-	EncodeDateTime(tm, fsec, &tz, &tzn, USE_ISO_DATES, buf);
-	len = (strlen(buf) + VARHDRSZ);
+	result = dt2local(timestamp, tz);
 
-	result = palloc(len);
-	VARATT_SIZEP(result) = len;
-	memmove(VARDATA(result), buf, (len - VARHDRSZ));
-
-	PG_RETURN_TEXT_P(result);
+	PG_RETURN_TIMESTAMP(result);
 }	/* timestamptz_izone() */
diff --git a/src/include/c.h b/src/include/c.h
index 29de386087901b4ec3f187ab5fcb7b0873af0b9e..52637717f58a7d11fd7c6546e772187ebc130f39 100644
--- a/src/include/c.h
+++ b/src/include/c.h
@@ -12,7 +12,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: c.h,v 1.115 2002/03/29 17:32:55 petere Exp $
+ * $Id: c.h,v 1.116 2002/04/21 19:48:18 thomas Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -302,6 +302,10 @@ typedef unsigned long int uint64;
 
 #endif /* not HAVE_LONG_INT_64 and not HAVE_LONG_LONG_INT_64 */
 
+#if defined(USE_INTEGER_DATETIMES) && !defined(INT64_IS_BUSTED)
+#define HAVE_INT64_TIMESTAMP
+#endif
+
 /* sig_atomic_t is required by ANSI C, but may be missing on old platforms */
 #ifndef HAVE_SIG_ATOMIC_T
 typedef int sig_atomic_t;
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
index 299cef2bb40d8ed8db9162ae6cf61d91f482d03d..00a00bf1b03ad69c1eaea6e9c08a1e028bc668d9 100644
--- a/src/include/catalog/catversion.h
+++ b/src/include/catalog/catversion.h
@@ -37,7 +37,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: catversion.h,v 1.121 2002/04/21 00:26:43 tgl Exp $
+ * $Id: catversion.h,v 1.122 2002/04/21 19:48:22 thomas Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -53,6 +53,6 @@
  */
 
 /*							yyyymmddN */
-#define CATALOG_VERSION_NO	200204201
+#define CATALOG_VERSION_NO	200204211
 
 #endif
diff --git a/src/include/catalog/pg_control.h b/src/include/catalog/pg_control.h
index 2bc01d6b171aa12cb7eeb2ad6641e29a23b3c970..27ed668f7b6b0153a5e71a38a669fce4ed9337f1 100644
--- a/src/include/catalog/pg_control.h
+++ b/src/include/catalog/pg_control.h
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_control.h,v 1.6 2001/11/05 17:46:32 momjian Exp $
+ * $Id: pg_control.h,v 1.7 2002/04/21 19:48:23 thomas Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -22,7 +22,7 @@
 
 
 /* Version identifier for this pg_control format */
-#define PG_CONTROL_VERSION	71
+#define PG_CONTROL_VERSION	72
 
 /*
  * Body of CheckPoint XLOG records.  This is declared here because we keep
@@ -106,7 +106,15 @@ typedef struct ControlFileData
 	 */
 	uint32		blcksz;			/* block size for this DB */
 	uint32		relseg_size;	/* blocks per segment of large relation */
+
+	uint32		nameDataLen;	/* catalog name field width */
+	uint32		funcMaxArgs;	/* maximum number of function arguments */
+
+	/* flag indicating internal format of timestamp, interval, time */
+	uint32		enableIntTimes;	/* int64 storage enabled? */
+
 	/* active locales --- "C" if compiled without USE_LOCALE: */
+	uint32		localeBuflen;
 	char		lc_collate[LOCALE_NAME_BUFLEN];
 	char		lc_ctype[LOCALE_NAME_BUFLEN];
 } ControlFileData;
diff --git a/src/include/catalog/pg_operator.h b/src/include/catalog/pg_operator.h
index 0cd1f5d96f0578d0d5fd0f37cb49a7d91a8e8bef..90484c95c8bb5f1fb12932f91324f8a6aeb204ea 100644
--- a/src/include/catalog/pg_operator.h
+++ b/src/include/catalog/pg_operator.h
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_operator.h,v 1.102 2002/04/16 23:08:11 tgl Exp $
+ * $Id: pg_operator.h,v 1.103 2002/04/21 19:48:23 thomas Exp $
  *
  * NOTES
  *	  the genbki.sh script reads this file and generates .bki
@@ -476,6 +476,8 @@ DATA(insert OID = 1068 ( ">"	   PGNSP PGUID 0 b t f 1043 1043	16 1066 1067  0 0
 DATA(insert OID = 1069 ( ">="	   PGNSP PGUID 0 b t f 1043 1043	16 1067 1066  0 0 0 0 varcharge scalargtsel scalargtjoinsel ));
 
 /* date operators */
+DATA(insert OID = 1076 ( "+"	   PGNSP PGUID 0 b t f  1082	1186 1114 0 0 0 0 0 0 date_pl_interval - - ));
+DATA(insert OID = 1077 ( "-"	   PGNSP PGUID 0 b t f  1082	1186 1114 0 0 0 0 0 0 date_mi_interval - - ));
 DATA(insert OID = 1093 ( "="	   PGNSP PGUID 0 b t t  1082	1082   16 1093 1094 1095 1095 1095 1097 date_eq eqsel eqjoinsel ));
 DATA(insert OID = 1094 ( "<>"	   PGNSP PGUID 0 b t f  1082	1082   16 1094 1093  0 0 0 0 date_ne neqsel neqjoinsel ));
 DATA(insert OID = 1095 ( "<"	   PGNSP PGUID 0 b t f  1082	1082   16 1097 1098  0 0 0 0 date_lt scalarltsel scalarltjoinsel ));
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index f8863d9340f6818fc5702c3493d0b4bb6f6d56b3..3cdf0a488e9ce98d423b49f2db31c4a0689ea14a 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_proc.h,v 1.228 2002/04/18 20:01:10 tgl Exp $
+ * $Id: pg_proc.h,v 1.229 2002/04/21 19:48:23 thomas Exp $
  *
  * NOTES
  *	  The script catalog/genbki.sh reads this file and generates .bki
@@ -1280,7 +1280,7 @@ DESCR("convert timetz to text");
 
 /* OIDS 1000 - 1999 */
 
-DATA(insert OID = 1026 (  timezone		   PGNSP PGUID 12 f t f t f s 2 25 "1186 1184" 100 0 0 100	timestamptz_izone - _null_ ));
+DATA(insert OID = 1026 (  timezone		   PGNSP PGUID 12 f t f t f s 2 1186 "1186 1184" 100 0 0 100	timestamptz_izone - _null_ ));
 DESCR("time zone");
 
 DATA(insert OID = 1029 (  nullvalue		   PGNSP PGUID 12 f t f f f i 1 16 "0" 100 0 0 100	nullvalue - _null_ ));
@@ -1414,8 +1414,8 @@ DATA(insert OID = 1156 (  timestamptz_ge   PGNSP PGUID 12 f t f t f i 2 16 "1184
 DESCR("greater-than-or-equal");
 DATA(insert OID = 1157 (  timestamptz_gt   PGNSP PGUID 12 f t f t f i 2 16 "1184 1184" 100 0 0 100	timestamp_gt - _null_ ));
 DESCR("greater-than");
-DATA(insert OID = 1159 (  timezone		   PGNSP PGUID 12 f t f t f s 2 25 "25 1184" 100 0 0 100  timestamptz_zone - _null_ ));
-DESCR("time zone");
+DATA(insert OID = 1159 (  timezone		   PGNSP PGUID 12 f t f t f s 2 1114 "25 1184" 100 0 0 100  timestamptz_zone - _null_ ));
+DESCR("timestamp at a specified time zone");
 
 DATA(insert OID = 1160 (  interval_in	   PGNSP PGUID 12 f t f t f s 1 1186 "0" 100 0 0 100  interval_in - _null_ ));
 DESCR("(internal)");
@@ -1710,13 +1710,13 @@ DATA(insert OID = 1383 (  date_part    PGNSP PGUID 14 f t f t f s 2  701 "25 703
 DESCR("extract field from reltime");
 DATA(insert OID = 1384 (  date_part    PGNSP PGUID 14 f t f t f i 2  701 "25 1082" 100 0 0 100	"select date_part($1, cast($2 as timestamp without time zone))" - _null_ ));
 DESCR("extract field from date");
-DATA(insert OID = 1385 (  date_part    PGNSP PGUID 14 f t f t f i 2  701 "25 1083" 100 0 0 100	"select date_part($1, cast($2 as time with time zone))" - _null_ ));
+DATA(insert OID = 1385 (  date_part	   PGNSP PGUID 12 f t f t f i 2  701 "25 1083" 100 0 0 100  time_part - _null_ ));
 DESCR("extract field from time");
 DATA(insert OID = 1386 (  age		   PGNSP PGUID 14 f t f t f s 1 1186 "1184" 100 0 0 100  "select age(cast(current_date as timestamp with time zone), $1)" - _null_ ));
 DESCR("date difference from today preserving months and years");
 
-DATA(insert OID = 1388 (  timetz		   PGNSP PGUID 12 f t f t f s 1 1266 "1184" 100 0 0 100  timestamptz_timetz - _null_ ));
-DESCR("convert timestamp to timetz");
+DATA(insert OID = 1388 (  timetz	   PGNSP PGUID 12 f t f t f s 1 1266 "1184" 100 0 0 100  timestamptz_timetz - _null_ ));
+DESCR("convert timestamptz to timetz");
 
 DATA(insert OID = 1389 (  isfinite	   PGNSP PGUID 12 f t f t f i 1 16 "1184" 100 0 0 100  timestamp_finite - _null_ ));
 DESCR("boolean test");
@@ -2769,6 +2769,8 @@ DESCR("return position of substring");
 DATA(insert OID = 2015 (  btrim			   PGNSP PGUID 12 f t f t f i 2 17 "17 17" 100 0 0 100	byteatrim - _null_ ));
 DESCR("trim both ends of string");
 
+DATA(insert OID = 2019 (  time				PGNSP PGUID 12 f t f t f s 1 1083 "1184" 100 0 0 100  timestamptz_time - _null_ ));
+DESCR("convert timestamptz to time");
 DATA(insert OID = 2020 (  date_trunc		PGNSP PGUID 12 f t f t f i 2 1114 "25 1114" 100 0 0 100  timestamp_trunc - _null_ ));
 DESCR("truncate timestamp to specified units");
 DATA(insert OID = 2021 (  date_part			PGNSP PGUID 12 f t f t f i 2  701 "25 1114" 100 0 0 100  timestamp_part - _null_ ));
@@ -2801,9 +2803,9 @@ DATA(insert OID = 2035 (  timestamp_smaller PGNSP PGUID 12 f t f t f i 2 1114 "1
 DESCR("smaller of two");
 DATA(insert OID = 2036 (  timestamp_larger	PGNSP PGUID 12 f t f t f i 2 1114 "1114 1114" 100 0 0 100  timestamp_larger - _null_ ));
 DESCR("larger of two");
-DATA(insert OID = 2037 (  timetz			PGNSP PGUID 12 f t f t f s 2 1266 "25 1266" 100 0 0 100  timetz_zone - _null_ ));
+DATA(insert OID = 2037 (  timezone			PGNSP PGUID 12 f t f t f s 2 1266 "25 1266" 100 0 0 100  timetz_zone - _null_ ));
 DESCR("time with time zone");
-DATA(insert OID = 2038 (  timetz			PGNSP PGUID 12 f t f t f i 2 1266 "1186 1266" 100 0 0 100  timetz_izone - _null_ ));
+DATA(insert OID = 2038 (  timezone			PGNSP PGUID 12 f t f t f i 2 1266 "1186 1266" 100 0 0 100  timetz_izone - _null_ ));
 DESCR("time with time zone");
 DATA(insert OID = 2041 ( overlaps			PGNSP PGUID 12 f t f f f i 4 16 "1114 1114 1114 1114" 100 0 0 100  overlaps_timestamp - _null_ ));
 DESCR("SQL92 interval comparison");
@@ -2843,10 +2845,15 @@ DATA(insert OID = 2058 (  age				PGNSP PGUID 12 f t f t f i 2 1186 "1114 1114" 1
 DESCR("date difference preserving months and years");
 DATA(insert OID = 2059 (  age				PGNSP PGUID 14 f t f t f s 1 1186 "1114" 100 0 0 100  "select age(cast(current_date as timestamp without time zone), $1)" - _null_ ));
 DESCR("date difference from today preserving months and years");
+
 DATA(insert OID = 2069 (  timezone			PGNSP PGUID 12 f t f t f s 2 1184 "25 1114" 100 0 0 100  timestamp_zone - _null_ ));
-DESCR("time zone");
+DESCR("timestamp at a specified time zone");
 DATA(insert OID = 2070 (  timezone			PGNSP PGUID 12 f t f t f s 2 1184 "1186 1114" 100 0 0 100  timestamp_izone - _null_ ));
 DESCR("time zone");
+DATA(insert OID = 2071 (  date_pl_interval	PGNSP PGUID 14 f t f t f i 2 1114 "1082 1186" 100 0 0 100  "select cast($1 as timestamp without time zone) + $2;" - _null_ ));
+DESCR("add");
+DATA(insert OID = 2072 (  date_mi_interval	PGNSP PGUID 14 f t f t f i 2 1114 "1082 1186" 100 0 0 100  "select cast($1 as timestamp without time zone) - $2;" - _null_ ));
+DESCR("subtract");
 
 /* Aggregates (moved here from pg_aggregate for 7.3) */
 
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index 2cae99aaefb64d74241ab94e3ff3d305823db457..80b904181d316dbc41243e5ee1ed9324c4b4a83b 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -8,7 +8,7 @@
  * or in pg_config.h afterwards.  Of course, if you edit pg_config.h, then your
  * changes will be overwritten the next time you run configure.
  *
- * $Id: pg_config.h.in,v 1.22 2002/04/21 00:22:52 ishii Exp $
+ * $Id: pg_config.h.in,v 1.23 2002/04/21 19:48:19 thomas Exp $
  */
 
 #ifndef PG_CONFIG_H
@@ -33,6 +33,9 @@
 /* A canonical string containing the version number, platform, and C compiler */
 #undef PG_VERSION_STR
 
+/* Set to 1 if you want 64-bit integer timestamp and interval support (--enable-integer-datetimes) */
+#undef USE_INTEGER_DATETIMES
+
 /* Set to 1 if you want cyrillic recode (--enable-recode) */
 #undef CYR_RECODE
 
diff --git a/src/include/utils/date.h b/src/include/utils/date.h
index ca911c0f7f0d650cb908a4476aff021e670852b4..209dd74d9dcb8b1731e2ee7b88896d43e8a9ccad 100644
--- a/src/include/utils/date.h
+++ b/src/include/utils/date.h
@@ -7,27 +7,41 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: date.h,v 1.17 2001/11/05 17:46:36 momjian Exp $
+ * $Id: date.h,v 1.18 2002/04/21 19:48:31 thomas Exp $
  *
  *-------------------------------------------------------------------------
  */
 #ifndef DATE_H
 #define DATE_H
 
+#include "c.h"
 #include "fmgr.h"
 
 
 typedef int32 DateADT;
 
+#ifdef HAVE_INT64_TIMESTAMP
+typedef int64 TimeADT;
+#else
 typedef float8 TimeADT;
+#endif
 
 typedef struct
 {
-	double		time;			/* all time units other than months and
-								 * years */
-	int32		zone;			/* numeric time zone, in seconds */
+#ifdef HAVE_INT64_TIMESTAMP
+	int64		time;	/* all time units other than months and years */
+#else
+	double		time;	/* all time units other than months and years */
+#endif
+	int32		zone;	/* numeric time zone, in seconds */
 } TimeTzADT;
 
+#ifdef HAVE_INT64_TIMESTAMP
+#define MAX_TIME_PRECISION 6
+#else
+#define MAX_TIME_PRECISION 13
+#endif
+
 /*
  * Macros for fmgr-callable functions.
  *
@@ -90,6 +104,7 @@ extern Datum time_larger(PG_FUNCTION_ARGS);
 extern Datum time_smaller(PG_FUNCTION_ARGS);
 extern Datum time_mi_time(PG_FUNCTION_ARGS);
 extern Datum timestamp_time(PG_FUNCTION_ARGS);
+extern Datum timestamptz_time(PG_FUNCTION_ARGS);
 extern Datum time_interval(PG_FUNCTION_ARGS);
 extern Datum interval_time(PG_FUNCTION_ARGS);
 extern Datum text_time(PG_FUNCTION_ARGS);
@@ -97,6 +112,7 @@ extern Datum time_text(PG_FUNCTION_ARGS);
 extern Datum time_pl_interval(PG_FUNCTION_ARGS);
 extern Datum time_mi_interval(PG_FUNCTION_ARGS);
 extern Datum interval_pl_time(PG_FUNCTION_ARGS);
+extern Datum time_part(PG_FUNCTION_ARGS);
 
 extern Datum timetz_in(PG_FUNCTION_ARGS);
 extern Datum timetz_out(PG_FUNCTION_ARGS);
diff --git a/src/include/utils/datetime.h b/src/include/utils/datetime.h
index 7858498a953fe267d501b4bab028942a8016713c..a889bd6c7bcc728cf92ce41ac980600daf4abbe1 100644
--- a/src/include/utils/datetime.h
+++ b/src/include/utils/datetime.h
@@ -9,7 +9,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: datetime.h,v 1.28 2002/01/01 02:54:33 thomas Exp $
+ * $Id: datetime.h,v 1.29 2002/04/21 19:48:31 thomas Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -198,15 +198,26 @@ typedef struct
 
 /* TMODULO()
  * Macro to replace modf(), which is broken on some platforms.
+ * t = input and remainder
+ * q = integer part
+ * u = divisor
  */
+#ifdef HAVE_INT64_TIMESTAMP
+#define TMODULO(t,q,u) \
+do { \
+	q = (t / u); \
+	if (q != 0) t -= (q * u); \
+} while(0)
+#else
 #define TMODULO(t,q,u) \
 do { \
 	q = ((t < 0)? ceil(t / u): floor(t / u)); \
-	if (q != 0) \
-		t -= rint(q * u); \
+	if (q != 0) t -= rint(q * u); \
 } while(0)
+#endif
 
-#ifdef __CYGWIN__
+/* Global variable holding time zone information. */
+#if defined(__CYGWIN__) || defined(N_PLAT_NLM)
 #define TIMEZONE_GLOBAL _timezone
 #else
 #define TIMEZONE_GLOBAL timezone
@@ -250,7 +261,7 @@ extern int	day_tab[2][13];
 
 
 extern void GetCurrentTime(struct tm * tm);
-extern void GetCurrentTimeUsec(struct tm * tm, double *fsec);
+extern void GetCurrentTimeUsec(struct tm * tm, fsec_t *fsec);
 extern void j2date(int jd, int *year, int *month, int *day);
 extern int	date2j(int year, int month, int day);
 
@@ -259,22 +270,22 @@ extern int ParseDateTime(char *timestr, char *lowstr,
 			  int maxfields, int *numfields);
 extern int DecodeDateTime(char **field, int *ftype,
 			   int nf, int *dtype,
-			   struct tm * tm, double *fsec, int *tzp);
+			   struct tm * tm, fsec_t *fsec, int *tzp);
 
 extern int DecodeTimeOnly(char **field, int *ftype,
 			   int nf, int *dtype,
-			   struct tm * tm, double *fsec, int *tzp);
+			   struct tm * tm, fsec_t *fsec, int *tzp);
 
-extern int DecodeDateDelta(char **field, int *ftype,
+extern int DecodeInterval(char **field, int *ftype,
 				int nf, int *dtype,
-				struct tm * tm, double *fsec);
+				struct tm * tm, fsec_t *fsec);
 
 extern int	DetermineLocalTimeZone(struct tm * tm);
 
 extern int	EncodeDateOnly(struct tm * tm, int style, char *str);
-extern int	EncodeTimeOnly(struct tm * tm, double fsec, int *tzp, 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	EncodeTimeOnly(struct tm * tm, fsec_t fsec, int *tzp, int style, char *str);
+extern int	EncodeDateTime(struct tm * tm, fsec_t fsec, int *tzp, char **tzn, int style, char *str);
+extern int	EncodeInterval(struct tm * tm, fsec_t fsec, int style, char *str);
 
 extern int	DecodeSpecial(int field, char *lowtoken, int *val);
 extern int	DecodeUnits(int field, char *lowtoken, int *val);
diff --git a/src/include/utils/int8.h b/src/include/utils/int8.h
index e2db00da38eb81e8f42692e008bd3baba96a83a9..e2947e0050863f95714d94c9704bff1914fa2017 100644
--- a/src/include/utils/int8.h
+++ b/src/include/utils/int8.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: int8.h,v 1.31 2001/11/05 17:46:36 momjian Exp $
+ * $Id: int8.h,v 1.32 2002/04/21 19:48:31 thomas Exp $
  *
  * NOTES
  * These data types are supported on all 64-bit architectures, and may
@@ -15,17 +15,25 @@
  *	is not currently supported, then please try to make it so, then post
  *	patches to the postgresql.org hackers mailing list.
  *
- * This code was written for and originally appeared in the contrib
- *	directory as a user-defined type.
- * - thomas 1998-06-08
- *
  *-------------------------------------------------------------------------
  */
 #ifndef INT8_H
 #define INT8_H
 
+#include "c.h"
 #include "fmgr.h"
 
+/* this should be set in pg_config.h, but just in case it wasn't: */
+#ifndef INT64_FORMAT
+#warning "Broken pg_config.h should have defined INT64_FORMAT"
+#define INT64_FORMAT "%ld"
+#endif
+
+#ifdef HAVE_LL_CONSTANTS
+#define INT64CONST(x)  ((int64) x##LL)
+#else
+#define INT64CONST(x)  ((int64) x)
+#endif
 
 extern Datum int8in(PG_FUNCTION_ARGS);
 extern Datum int8out(PG_FUNCTION_ARGS);
diff --git a/src/include/utils/timestamp.h b/src/include/utils/timestamp.h
index 3ea20f3ea2440357d851b62bc3a65507dd062027..a4da9dd5d6b9dbd27e7e0c784bf29316db2d7c42 100644
--- a/src/include/utils/timestamp.h
+++ b/src/include/utils/timestamp.h
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: timestamp.h,v 1.24 2001/11/05 17:46:36 momjian Exp $
+ * $Id: timestamp.h,v 1.25 2002/04/21 19:48:31 thomas Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -18,8 +18,11 @@
 #include <limits.h>
 #include <float.h>
 
+#include "c.h"
 #include "fmgr.h"
-
+#ifdef HAVE_INT64_TIMESTAMP
+#include "utils/int8.h"
+#endif
 
 /*
  * Timestamp represents absolute time.
@@ -31,16 +34,22 @@
  *	consisting of a beginning and ending time, not a time span - thomas 97/03/20
  */
 
+#ifdef HAVE_INT64_TIMESTAMP
+typedef int64 Timestamp;
+typedef int64 TimestampTz;
+#else
 typedef double Timestamp;
-
 typedef double TimestampTz;
+#endif
 
 typedef struct
 {
-	double		time;			/* all time units other than months and
-								 * years */
-	int32		month;			/* months and years, after time for
-								 * alignment */
+#ifdef HAVE_INT64_TIMESTAMP
+	int64		time;	/* all time units other than months and years */
+#else
+	double		time;	/* all time units other than months and years */
+#endif
+	int32		month;	/* months and years, after time for alignment */
 } Interval;
 
 
@@ -50,6 +59,27 @@ typedef struct
  * For Timestamp, we make use of the same support routines as for float8.
  * Therefore Timestamp is pass-by-reference if and only if float8 is!
  */
+#ifdef HAVE_INT64_TIMESTAMP
+#define DatumGetTimestamp(X)  ((Timestamp) DatumGetInt64(X))
+#define DatumGetTimestampTz(X)	((TimestampTz) DatumGetInt64(X))
+#define DatumGetIntervalP(X)  ((Interval *) DatumGetPointer(X))
+
+#define TimestampGetDatum(X) Int64GetDatum(X)
+#define TimestampTzGetDatum(X) Int64GetDatum(X)
+#define IntervalPGetDatum(X) PointerGetDatum(X)
+
+#define PG_GETARG_TIMESTAMP(n) PG_GETARG_INT64(n)
+#define PG_GETARG_TIMESTAMPTZ(n) PG_GETARG_INT64(n)
+#define PG_GETARG_INTERVAL_P(n) DatumGetIntervalP(PG_GETARG_DATUM(n))
+
+#define PG_RETURN_TIMESTAMP(x) PG_RETURN_INT64(x)
+#define PG_RETURN_TIMESTAMPTZ(x) PG_RETURN_INT64(x)
+#define PG_RETURN_INTERVAL_P(x) return IntervalPGetDatum(x)
+
+#define DT_NOBEGIN		(-INT64CONST(0x7fffffffffffffff) - 1)
+#define DT_NOEND		(INT64CONST(0x7fffffffffffffff))
+
+#else
 #define DatumGetTimestamp(X)  ((Timestamp) DatumGetFloat8(X))
 #define DatumGetTimestampTz(X)	((TimestampTz) DatumGetFloat8(X))
 #define DatumGetIntervalP(X)  ((Interval *) DatumGetPointer(X))
@@ -66,7 +96,6 @@ typedef struct
 #define PG_RETURN_TIMESTAMPTZ(x) return TimestampTzGetDatum(x)
 #define PG_RETURN_INTERVAL_P(x) return IntervalPGetDatum(x)
 
-
 #ifdef HUGE_VAL
 #define DT_NOBEGIN		(-HUGE_VAL)
 #define DT_NOEND		(HUGE_VAL)
@@ -74,6 +103,7 @@ typedef struct
 #define DT_NOBEGIN		(-DBL_MAX)
 #define DT_NOEND		(DBL_MAX)
 #endif
+#endif
 
 #define TIMESTAMP_NOBEGIN(j)	do {j = DT_NOBEGIN;} while (0)
 #define TIMESTAMP_IS_NOBEGIN(j) ((j) == DT_NOBEGIN)
@@ -83,8 +113,21 @@ typedef struct
 
 #define TIMESTAMP_NOT_FINITE(j) (TIMESTAMP_IS_NOBEGIN(j) || TIMESTAMP_IS_NOEND(j))
 
+
+#define MAX_TIMESTAMP_PRECISION 6
+#define MAX_INTERVAL_PRECISION 6
+
+#ifdef HAVE_INT64_TIMESTAMP
+typedef int32 fsec_t;
+
+#define SECONDS_TO_TIMESTAMP(x) (INT64CONST(x000000))
+#else
+typedef double fsec_t;
+
+#define SECONDS_TO_TIMESTAMP(x) (xe0)
 #define TIME_PREC_INV 1000000.0
 #define JROUND(j) (rint(((double) (j))*TIME_PREC_INV)/TIME_PREC_INV)
+#endif
 
 
 /*
@@ -167,13 +210,13 @@ extern Datum now(PG_FUNCTION_ARGS);
 
 /* Internal routines (not fmgr-callable) */
 
-extern int	tm2timestamp(struct tm * tm, double fsec, int *tzp, Timestamp *dt);
+extern int	tm2timestamp(struct tm * tm, fsec_t fsec, int *tzp, Timestamp *dt);
 extern int timestamp2tm(Timestamp dt, int *tzp, struct tm * tm,
-			 double *fsec, char **tzn);
-extern void dt2time(Timestamp dt, int *hour, int *min, double *sec);
+			 fsec_t *fsec, char **tzn);
+extern void dt2time(Timestamp dt, int *hour, int *min, int *sec, fsec_t *fsec);
 
-extern int	interval2tm(Interval span, struct tm * tm, float8 *fsec);
-extern int	tm2interval(struct tm * tm, double fsec, Interval *span);
+extern int	interval2tm(Interval span, struct tm * tm, fsec_t *fsec);
+extern int	tm2interval(struct tm * tm, fsec_t fsec, Interval *span);
 
 extern Timestamp SetEpochTimestamp(void);
 extern void GetEpochTime(struct tm * tm);
diff --git a/src/test/regress/expected/horology.out b/src/test/regress/expected/horology.out
index bcace859ce7424d4a3b6414a3f983da4ee5cbb32..4315019210d04f3fac8d3a3a75b8d2bf2296beaa 100644
--- a/src/test/regress/expected/horology.out
+++ b/src/test/regress/expected/horology.out
@@ -264,22 +264,22 @@ SELECT date '2001-02-03' + time with time zone '04:05:06 UTC' AS "Date + Time UT
 (1 row)
 
 SELECT date '1991-02-03' + interval '2 years' AS "Add Two Years";
-        Add Two Years         
-------------------------------
- Wed Feb 03 00:00:00 1993 PST
+      Add Two Years       
+--------------------------
+ Wed Feb 03 00:00:00 1993
 (1 row)
 
 SELECT date '2001-12-13' - interval '2 years' AS "Subtract Two Years";
-      Subtract Two Years      
-------------------------------
- Mon Dec 13 00:00:00 1999 PST
+    Subtract Two Years    
+--------------------------
+ Mon Dec 13 00:00:00 1999
 (1 row)
 
 -- subtract time from date should not make sense; use interval instead
 SELECT date '1991-02-03' - time '04:05:06' AS "Subtract Time";
-        Subtract Time         
-------------------------------
- Sat Feb 02 19:54:54 1991 PST
+      Subtract Time       
+--------------------------
+ Sat Feb 02 19:54:54 1991
 (1 row)
 
 SELECT date '1991-02-03' - time with time zone '04:05:06 UTC' AS "Subtract Time UTC";
@@ -406,7 +406,7 @@ SELECT '' AS "64", d1 + interval '1 year' AS one_year FROM TIMESTAMP_TBL;
     | Sat Feb 14 17:32:01 1998
     | Sun Feb 15 17:32:01 1998
     | Mon Feb 16 17:32:01 1998
-    | Thu Feb 16 17:32 0096 BC
+    | Thu Feb 16 17:32:01 0096 BC
     | Sun Feb 16 17:32:01 0098
     | Fri Feb 16 17:32:01 0598
     | Wed Feb 16 17:32:01 1098
@@ -475,7 +475,7 @@ SELECT '' AS "64", d1 - interval '1 year' AS one_year FROM TIMESTAMP_TBL;
     | Wed Feb 14 17:32:01 1996
     | Thu Feb 15 17:32:01 1996
     | Fri Feb 16 17:32:01 1996
-    | Mon Feb 16 17:32 0098 BC
+    | Mon Feb 16 17:32:01 0098 BC
     | Thu Feb 16 17:32:01 0096
     | Tue Feb 16 17:32:01 0596
     | Sun Feb 16 17:32:01 1096
@@ -622,7 +622,7 @@ SELECT '' AS "64", d1 + interval '1 year' AS one_year FROM TIMESTAMPTZ_TBL;
     | Sat Feb 14 17:32:01 1998 PST
     | Sun Feb 15 17:32:01 1998 PST
     | Mon Feb 16 17:32:01 1998 PST
-    | Thu Feb 16 17:32 0096 BC
+    | Thu Feb 16 17:32:01 0096 BC
     | Sun Feb 16 17:32:01 0098
     | Fri Feb 16 17:32:01 0598
     | Wed Feb 16 17:32:01 1098
@@ -691,7 +691,7 @@ SELECT '' AS "64", d1 - interval '1 year' AS one_year FROM TIMESTAMPTZ_TBL;
     | Wed Feb 14 17:32:01 1996 PST
     | Thu Feb 15 17:32:01 1996 PST
     | Fri Feb 16 17:32:01 1996 PST
-    | Mon Feb 16 17:32 0098 BC
+    | Mon Feb 16 17:32:01 0098 BC
     | Thu Feb 16 17:32:01 0096
     | Tue Feb 16 17:32:01 0596
     | Sun Feb 16 17:32:01 1096
@@ -1519,7 +1519,7 @@ SELECT (time '00:00', interval '1 hour')
  f
 (1 row)
 
-CREATE TABLE TEMP_TIMESTAMP (f1 timestamp);
+CREATE TABLE TEMP_TIMESTAMP (f1 timestamp with time zone);
 -- get some candidate input values
 INSERT INTO TEMP_TIMESTAMP (f1)
   SELECT d1 FROM TIMESTAMP_TBL
@@ -1883,8 +1883,9 @@ SELECT '' AS "160", d.f1 AS "timestamp", t.f1 AS "interval", d.f1 - t.f1 AS minu
      | Sat Sep 22 18:19:20 2001 PDT | @ 14 secs ago                 | Sat Sep 22 18:19:34 2001 PDT
 (160 rows)
 
-SELECT '' AS "16", d.f1 AS "timestamp", timestamp '1980-01-06 00:00 GMT' AS gpstime_zero,
-   d.f1 - timestamp '1980-01-06 00:00 GMT' AS difference
+SELECT '' AS "16", d.f1 AS "timestamp",
+   timestamp with time zone '1980-01-06 00:00 GMT' AS gpstime_zero,
+   d.f1 - timestamp with time zone '1980-01-06 00:00 GMT' AS difference
   FROM TEMP_TIMESTAMP d
   ORDER BY difference;
  16 |          timestamp           |         gpstime_zero         |             difference              
@@ -2305,7 +2306,7 @@ SELECT '' AS two, d1 AS "timestamp", abstime(d1) AS abstime
 
 SELECT '' AS three, f1 as abstime, cast(f1 as timestamp) AS "timestamp"
   FROM ABSTIME_TBL WHERE NOT isfinite(f1);
-ERROR:  Unable to convert abstime 'invalid' to timestamptz
+ERROR:  Unable to convert abstime 'invalid' to timestamp
 SELECT '' AS ten, f1 AS interval, reltime(f1) AS reltime
   FROM INTERVAL_TBL;
  ten |           interval            |            reltime            
@@ -2385,7 +2386,7 @@ SELECT '' AS "64", d1 AS us_postgres FROM TIMESTAMP_TBL;
     | Fri Feb 14 17:32:01 1997
     | Sat Feb 15 17:32:01 1997
     | Sun Feb 16 17:32:01 1997
-    | Tue Feb 16 17:32 0097 BC
+    | Tue Feb 16 17:32:01 0097 BC
     | Sat Feb 16 17:32:01 0097
     | Thu Feb 16 17:32:01 0597
     | Tue Feb 16 17:32:01 1097
@@ -2467,7 +2468,7 @@ SELECT '' AS "64", d1 AS us_iso FROM TIMESTAMP_TBL;
     | 1997-02-14 17:32:01
     | 1997-02-15 17:32:01
     | 1997-02-16 17:32:01
-    | 0097-02-16 17:32 BC
+    | 0097-02-16 17:32:01 BC
     | 0097-02-16 17:32:01
     | 0597-02-16 17:32:01
     | 1097-02-16 17:32:01
@@ -2551,7 +2552,7 @@ SELECT '' AS "64", d1 AS us_sql FROM TIMESTAMP_TBL;
     | 02/14/1997 17:32:01
     | 02/15/1997 17:32:01
     | 02/16/1997 17:32:01
-    | 02/16/0097 17:32 BC
+    | 02/16/0097 17:32:01 BC
     | 02/16/0097 17:32:01
     | 02/16/0597 17:32:01
     | 02/16/1097 17:32:01
@@ -2642,7 +2643,7 @@ SELECT '' AS "65", d1 AS european_postgres FROM TIMESTAMP_TBL;
     | Fri 14 Feb 17:32:01 1997
     | Sat 15 Feb 17:32:01 1997
     | Sun 16 Feb 17:32:01 1997
-    | Tue 16 Feb 17:32 0097 BC
+    | Tue 16 Feb 17:32:01 0097 BC
     | Sat 16 Feb 17:32:01 0097
     | Thu 16 Feb 17:32:01 0597
     | Tue 16 Feb 17:32:01 1097
@@ -2727,7 +2728,7 @@ SELECT '' AS "65", d1 AS european_iso FROM TIMESTAMP_TBL;
     | 1997-02-14 17:32:01
     | 1997-02-15 17:32:01
     | 1997-02-16 17:32:01
-    | 0097-02-16 17:32 BC
+    | 0097-02-16 17:32:01 BC
     | 0097-02-16 17:32:01
     | 0597-02-16 17:32:01
     | 1097-02-16 17:32:01
@@ -2812,7 +2813,7 @@ SELECT '' AS "65", d1 AS european_sql FROM TIMESTAMP_TBL;
     | 14/02/1997 17:32:01
     | 15/02/1997 17:32:01
     | 16/02/1997 17:32:01
-    | 16/02/0097 17:32 BC
+    | 16/02/0097 17:32:01 BC
     | 16/02/0097 17:32:01
     | 16/02/0597 17:32:01
     | 16/02/1097 17:32:01
diff --git a/src/test/regress/expected/timestamp.out b/src/test/regress/expected/timestamp.out
index ad2f1d7ec9766ab49d5d33d16371925fedc394f2..e7c8cc8086b7c42a0e63058eabcf367e1ed80ba2 100644
--- a/src/test/regress/expected/timestamp.out
+++ b/src/test/regress/expected/timestamp.out
@@ -183,7 +183,7 @@ SELECT '' AS "64", d1 FROM TIMESTAMP_TBL;
     | Fri Feb 14 17:32:01 1997
     | Sat Feb 15 17:32:01 1997
     | Sun Feb 16 17:32:01 1997
-    | Tue Feb 16 17:32 0097 BC
+    | Tue Feb 16 17:32:01 0097 BC
     | Sat Feb 16 17:32:01 0097
     | Thu Feb 16 17:32:01 0597
     | Tue Feb 16 17:32:01 1097
@@ -265,11 +265,11 @@ SELECT '' AS "48", d1 FROM TIMESTAMP_TBL
 
 SELECT '' AS "15", d1 FROM TIMESTAMP_TBL
    WHERE d1 < timestamp without time zone '1997-01-02';
- 15 |            d1            
-----+--------------------------
+ 15 |             d1              
+----+-----------------------------
     | -infinity
     | Thu Jan 01 00:00:00 1970
-    | Tue Feb 16 17:32 0097 BC
+    | Tue Feb 16 17:32:01 0097 BC
     | Sat Feb 16 17:32:01 0097
     | Thu Feb 16 17:32:01 0597
     | Tue Feb 16 17:32:01 1097
@@ -335,7 +335,7 @@ SELECT '' AS "63", d1 FROM TIMESTAMP_TBL
     | Fri Feb 14 17:32:01 1997
     | Sat Feb 15 17:32:01 1997
     | Sun Feb 16 17:32:01 1997
-    | Tue Feb 16 17:32 0097 BC
+    | Tue Feb 16 17:32:01 0097 BC
     | Sat Feb 16 17:32:01 0097
     | Thu Feb 16 17:32:01 0597
     | Tue Feb 16 17:32:01 1097
@@ -362,12 +362,12 @@ SELECT '' AS "63", d1 FROM TIMESTAMP_TBL
 
 SELECT '' AS "16", d1 FROM TIMESTAMP_TBL
    WHERE d1 <= timestamp without time zone '1997-01-02';
- 16 |            d1            
-----+--------------------------
+ 16 |             d1              
+----+-----------------------------
     | -infinity
     | Thu Jan 01 00:00:00 1970
     | Thu Jan 02 00:00:00 1997
-    | Tue Feb 16 17:32 0097 BC
+    | Tue Feb 16 17:32:01 0097 BC
     | Sat Feb 16 17:32:01 0097
     | Thu Feb 16 17:32:01 0597
     | Tue Feb 16 17:32:01 1097
diff --git a/src/test/regress/expected/timestamptz.out b/src/test/regress/expected/timestamptz.out
index 1741add0ac0d45a304b12c246b5f3cdf0ce0f61d..403a0bbd4afc94cf72ab52a32e343d6a72b3f704 100644
--- a/src/test/regress/expected/timestamptz.out
+++ b/src/test/regress/expected/timestamptz.out
@@ -178,7 +178,7 @@ SELECT '' AS "64", d1 FROM TIMESTAMPTZ_TBL;
     | Fri Feb 14 17:32:01 1997 PST
     | Sat Feb 15 17:32:01 1997 PST
     | Sun Feb 16 17:32:01 1997 PST
-    | Tue Feb 16 17:32 0097 BC
+    | Tue Feb 16 17:32:01 0097 BC
     | Sat Feb 16 17:32:01 0097
     | Thu Feb 16 17:32:01 0597
     | Tue Feb 16 17:32:01 1097
@@ -264,7 +264,7 @@ SELECT '' AS "15", d1 FROM TIMESTAMPTZ_TBL
 ----+------------------------------
     | -infinity
     | Wed Dec 31 16:00:00 1969 PST
-    | Tue Feb 16 17:32 0097 BC
+    | Tue Feb 16 17:32:01 0097 BC
     | Sat Feb 16 17:32:01 0097
     | Thu Feb 16 17:32:01 0597
     | Tue Feb 16 17:32:01 1097
@@ -330,7 +330,7 @@ SELECT '' AS "63", d1 FROM TIMESTAMPTZ_TBL
     | Fri Feb 14 17:32:01 1997 PST
     | Sat Feb 15 17:32:01 1997 PST
     | Sun Feb 16 17:32:01 1997 PST
-    | Tue Feb 16 17:32 0097 BC
+    | Tue Feb 16 17:32:01 0097 BC
     | Sat Feb 16 17:32:01 0097
     | Thu Feb 16 17:32:01 0597
     | Tue Feb 16 17:32:01 1097
@@ -362,7 +362,7 @@ SELECT '' AS "16", d1 FROM TIMESTAMPTZ_TBL
     | -infinity
     | Wed Dec 31 16:00:00 1969 PST
     | Thu Jan 02 00:00:00 1997 PST
-    | Tue Feb 16 17:32 0097 BC
+    | Tue Feb 16 17:32:01 0097 BC
     | Sat Feb 16 17:32:01 0097
     | Thu Feb 16 17:32:01 0597
     | Tue Feb 16 17:32:01 1097
diff --git a/src/test/regress/sql/horology.sql b/src/test/regress/sql/horology.sql
index 019c3e9ffd7f77d57008d64e895a656f817d50e2..136e6c6c6517c046afe3b27bec4d9660b4084593 100644
--- a/src/test/regress/sql/horology.sql
+++ b/src/test/regress/sql/horology.sql
@@ -214,7 +214,7 @@ SELECT (time '00:00', interval '1 hour')
 SELECT (time '00:00', interval '1 hour')
   OVERLAPS (time '01:30', interval '1 day') AS "False";
 
-CREATE TABLE TEMP_TIMESTAMP (f1 timestamp);
+CREATE TABLE TEMP_TIMESTAMP (f1 timestamp with time zone);
 
 -- get some candidate input values
 
@@ -236,8 +236,9 @@ SELECT '' AS "160", d.f1 AS "timestamp", t.f1 AS "interval", d.f1 - t.f1 AS minu
   WHERE isfinite(d.f1)
   ORDER BY minus, "timestamp", "interval";
 
-SELECT '' AS "16", d.f1 AS "timestamp", timestamp '1980-01-06 00:00 GMT' AS gpstime_zero,
-   d.f1 - timestamp '1980-01-06 00:00 GMT' AS difference
+SELECT '' AS "16", d.f1 AS "timestamp",
+   timestamp with time zone '1980-01-06 00:00 GMT' AS gpstime_zero,
+   d.f1 - timestamp with time zone '1980-01-06 00:00 GMT' AS difference
   FROM TEMP_TIMESTAMP d
   ORDER BY difference;