Index: src/backend/utils/adt/date.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/utils/adt/date.c,v
retrieving revision 1.109
diff -c -r1.109 date.c
*** src/backend/utils/adt/date.c	26 May 2005 02:04:13 -0000	1.109
--- src/backend/utils/adt/date.c	6 Jun 2005 17:30:25 -0000
***************
*** 18,23 ****
--- 18,24 ----
  #include <ctype.h>
  #include <limits.h>
  #include <float.h>
+ #include <time.h> 
  
  #include "access/hash.h"
  #include "libpq/pqformat.h"
***************
*** 724,730 ****
  	if (TIMESTAMP_NOT_FINITE(timestamp))
  		PG_RETURN_NULL();
  
! 	if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL) !=0)
  		ereport(ERROR,
  				(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
  				 errmsg("timestamp out of range")));
--- 725,731 ----
  	if (TIMESTAMP_NOT_FINITE(timestamp))
  		PG_RETURN_NULL();
  
! 	if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) !=0)
  		ereport(ERROR,
  				(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
  				 errmsg("timestamp out of range")));
***************
*** 767,773 ****
  	if (TIMESTAMP_NOT_FINITE(timestamp))
  		PG_RETURN_NULL();
  
! 	if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn) !=0)
  		ereport(ERROR,
  				(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
  				 errmsg("timestamp out of range")));
--- 768,774 ----
  	if (TIMESTAMP_NOT_FINITE(timestamp))
  		PG_RETURN_NULL();
  
! 	if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn, NULL) !=0)
  		ereport(ERROR,
  				(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
  				 errmsg("timestamp out of range")));
***************
*** 1327,1333 ****
  	if (TIMESTAMP_NOT_FINITE(timestamp))
  		PG_RETURN_NULL();
  
! 	if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL) !=0)
  		ereport(ERROR,
  				(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
  				 errmsg("timestamp out of range")));
--- 1328,1334 ----
  	if (TIMESTAMP_NOT_FINITE(timestamp))
  		PG_RETURN_NULL();
  
! 	if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) !=0)
  		ereport(ERROR,
  				(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
  				 errmsg("timestamp out of range")));
***************
*** 1364,1370 ****
  	if (TIMESTAMP_NOT_FINITE(timestamp))
  		PG_RETURN_NULL();
  
! 	if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn) !=0)
  		ereport(ERROR,
  				(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
  				 errmsg("timestamp out of range")));
--- 1365,1371 ----
  	if (TIMESTAMP_NOT_FINITE(timestamp))
  		PG_RETURN_NULL();
  
! 	if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn, NULL) !=0)
  		ereport(ERROR,
  				(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
  				 errmsg("timestamp out of range")));
***************
*** 2247,2253 ****
  	if (TIMESTAMP_NOT_FINITE(timestamp))
  		PG_RETURN_NULL();
  
! 	if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn) !=0)
  		ereport(ERROR,
  				(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
  				 errmsg("timestamp out of range")));
--- 2248,2254 ----
  	if (TIMESTAMP_NOT_FINITE(timestamp))
  		PG_RETURN_NULL();
  
! 	if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn, NULL) !=0)
  		ereport(ERROR,
  				(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
  				 errmsg("timestamp out of range")));
***************
*** 2463,2515 ****
  
  /* timetz_zone()
   * Encode time with time zone type with specified time zone.
   */
  Datum
  timetz_zone(PG_FUNCTION_ARGS)
  {
  	text	   *zone = PG_GETARG_TEXT_P(0);
! 	TimeTzADT  *time = PG_GETARG_TIMETZADT_P(1);
  	TimeTzADT  *result;
  	int			tz;
! 	int			type,
! 				val;
! 	char	   *lowzone;
! 
! 	lowzone = downcase_truncate_identifier(VARDATA(zone),
! 										   VARSIZE(zone) - VARHDRSZ,
! 										   false);
! 
! 	type = DecodeSpecial(0, lowzone, &val);
  
! 	result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
  
! 	if (type == TZ || type == DTZ)
! 	{
! 		tz = val * 60;
  #ifdef HAVE_INT64_TIMESTAMP
! 		result->time = time->time + (time->zone - tz) * USECS_PER_SEC;
! 		while (result->time < INT64CONST(0))
! 			result->time += USECS_PER_DAY;
! 		while (result->time >= USECS_PER_DAY)
! 			result->time -= USECS_PER_DAY;
  #else
! 		result->time = time->time + (time->zone - tz);
! 		while (result->time < 0)
! 			result->time += SECS_PER_DAY;
! 		while (result->time >= SECS_PER_DAY)
! 			result->time -= SECS_PER_DAY;
  #endif
  
! 		result->zone = tz;
! 	}
! 	else
! 	{
! 		ereport(ERROR,
! 				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
! 				 errmsg("time zone \"%s\" not recognized", lowzone)));
! 
! 		PG_RETURN_NULL();
! 	}
  
  	PG_RETURN_TIMETZADT_P(result);
  }	/* timetz_zone() */
--- 2464,2523 ----
  
  /* timetz_zone()
   * Encode time with time zone type with specified time zone.
+  * Applies DST rules as of the current date.
   */
  Datum
  timetz_zone(PG_FUNCTION_ARGS)
  {
  	text	   *zone = PG_GETARG_TEXT_P(0);
! 	TimeTzADT  *t = PG_GETARG_TIMETZADT_P(1);
  	TimeTzADT  *result;
  	int			tz;
! 	char        tzname[TZ_STRLEN_MAX];
! 	int         len;
! 	pg_tz	   *tzp;
! 	struct pg_tm *tm;
! 	pg_time_t   now;
! 
! 	/* Find the specified timezone */ 
! 	len = (VARSIZE(zone)-VARHDRSZ>TZ_STRLEN_MAX)?TZ_STRLEN_MAX:(VARSIZE(zone)-VARHDRSZ);
! 	memcpy(tzname,VARDATA(zone),len);
! 	tzname[len]=0;
! 	tzp = pg_tzset(tzname);
! 	if (!tzp) {
! 		ereport(ERROR,
! 			(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
! 		 	 errmsg("time zone \"%s\" not recognized", tzname)));
! 		PG_RETURN_NULL();
! 	}
  
! 	/* Get the offset-from-GMT that is valid today for the selected zone */
! 	if ((now = time(NULL)) < 0 ||
! 	    (tm = pg_localtime(&now, tzp)) == NULL) {
! 	   	ereport(ERROR,
! 	   		(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
! 			 errmsg("could not determine current time")));
! 		PG_RETURN_NULL();
! 	}
  
! 	result = (TimeTzADT *)palloc(sizeof(TimeTzADT));
! 	
! 	tz = -tm->tm_gmtoff;
  #ifdef HAVE_INT64_TIMESTAMP
! 	result->time = t->time + (t->zone - tz) * USECS_PER_SEC;
! 	while (result->time < INT64CONST(0))
! 		result->time += USECS_PER_DAY;
! 	while (result->time >= USECS_PER_DAY)
! 		result->time -= USECS_PER_DAY;
  #else
! 	result->time = t->time + (t->zone - tz);
! 	while (result->time < 0)
! 		result->time += SECS_PER_DAY;
! 	while (result->time >= SECS_PER_DAY)
! 		result->time -= SECS_PER_DAY;
  #endif
  
! 	result->zone = tz;
  
  	PG_RETURN_TIMETZADT_P(result);
  }	/* timetz_zone() */
Index: src/backend/utils/adt/formatting.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/utils/adt/formatting.c,v
retrieving revision 1.87
diff -c -r1.87 formatting.c
*** src/backend/utils/adt/formatting.c	25 May 2005 21:40:40 -0000	1.87
--- src/backend/utils/adt/formatting.c	6 Jun 2005 17:30:26 -0000
***************
*** 2910,2916 ****
  
  	ZERO_tmtc(&tmtc);
  
! 	if (timestamp2tm(dt, NULL, tmtcTm(&tmtc), &tmtcFsec(&tmtc), NULL) != 0)
  		ereport(ERROR,
  				(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
  				 errmsg("timestamp out of range")));
--- 2910,2916 ----
  
  	ZERO_tmtc(&tmtc);
  
! 	if (timestamp2tm(dt, NULL, tmtcTm(&tmtc), &tmtcFsec(&tmtc), NULL, NULL) != 0)
  		ereport(ERROR,
  				(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
  				 errmsg("timestamp out of range")));
***************
*** 2935,2941 ****
  
  	ZERO_tmtc(&tmtc);
  
! 	if (timestamp2tm(dt, &tz, tmtcTm(&tmtc), &tmtcFsec(&tmtc), &tmtcTzn(&tmtc)) != 0)
  		ereport(ERROR,
  				(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
  				 errmsg("timestamp out of range")));
--- 2935,2941 ----
  
  	ZERO_tmtc(&tmtc);
  
! 	if (timestamp2tm(dt, &tz, tmtcTm(&tmtc), &tmtcFsec(&tmtc), &tmtcTzn(&tmtc), NULL) != 0)
  		ereport(ERROR,
  				(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
  				 errmsg("timestamp out of range")));
Index: src/backend/utils/adt/nabstime.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/utils/adt/nabstime.c,v
retrieving revision 1.132
diff -c -r1.132 nabstime.c
*** src/backend/utils/adt/nabstime.c	26 May 2005 02:04:13 -0000	1.132
--- src/backend/utils/adt/nabstime.c	6 Jun 2005 17:30:27 -0000
***************
*** 556,562 ****
  		result = NOSTART_ABSTIME;
  	else if (TIMESTAMP_IS_NOEND(timestamp))
  		result = NOEND_ABSTIME;
! 	else if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL) == 0)
  	{
  		tz = DetermineLocalTimeZone(tm);
  		result = tm2abstime(tm, tz);
--- 556,562 ----
  		result = NOSTART_ABSTIME;
  	else if (TIMESTAMP_IS_NOEND(timestamp))
  		result = NOEND_ABSTIME;
! 	else if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) == 0)
  	{
  		tz = DetermineLocalTimeZone(tm);
  		result = tm2abstime(tm, tz);
***************
*** 632,638 ****
  		result = NOSTART_ABSTIME;
  	else if (TIMESTAMP_IS_NOEND(timestamp))
  		result = NOEND_ABSTIME;
! 	else if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL) == 0)
  		result = tm2abstime(tm, 0);
  	else
  	{
--- 632,638 ----
  		result = NOSTART_ABSTIME;
  	else if (TIMESTAMP_IS_NOEND(timestamp))
  		result = NOEND_ABSTIME;
! 	else if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) == 0)
  		result = tm2abstime(tm, 0);
  	else
  	{
Index: src/backend/utils/adt/timestamp.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/utils/adt/timestamp.c,v
retrieving revision 1.124
diff -c -r1.124 timestamp.c
*** src/backend/utils/adt/timestamp.c	26 May 2005 02:04:13 -0000	1.124
--- src/backend/utils/adt/timestamp.c	6 Jun 2005 17:30:27 -0000
***************
*** 142,148 ****
  
  	if (TIMESTAMP_NOT_FINITE(timestamp))
  		EncodeSpecialTimestamp(timestamp, buf);
! 	else if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL) == 0)
  		EncodeDateTime(tm, fsec, NULL, &tzn, DateStyle, buf);
  	else
  		ereport(ERROR,
--- 142,148 ----
  
  	if (TIMESTAMP_NOT_FINITE(timestamp))
  		EncodeSpecialTimestamp(timestamp, buf);
! 	else if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) == 0)
  		EncodeDateTime(tm, fsec, NULL, &tzn, DateStyle, buf);
  	else
  		ereport(ERROR,
***************
*** 178,184 ****
  	/* rangecheck: see if timestamp_out would like it */
  	if (TIMESTAMP_NOT_FINITE(timestamp))
  		 /* ok */ ;
! 	else if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL) !=0)
  		ereport(ERROR,
  				(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
  				 errmsg("timestamp out of range")));
--- 178,184 ----
  	/* rangecheck: see if timestamp_out would like it */
  	if (TIMESTAMP_NOT_FINITE(timestamp))
  		 /* ok */ ;
! 	else if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) !=0)
  		ereport(ERROR,
  				(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
  				 errmsg("timestamp out of range")));
***************
*** 381,387 ****
  
  	if (TIMESTAMP_NOT_FINITE(dt))
  		EncodeSpecialTimestamp(dt, buf);
! 	else if (timestamp2tm(dt, &tz, tm, &fsec, &tzn) == 0)
  		EncodeDateTime(tm, fsec, &tz, &tzn, DateStyle, buf);
  	else
  		ereport(ERROR,
--- 381,387 ----
  
  	if (TIMESTAMP_NOT_FINITE(dt))
  		EncodeSpecialTimestamp(dt, buf);
! 	else if (timestamp2tm(dt, &tz, tm, &fsec, &tzn, NULL) == 0)
  		EncodeDateTime(tm, fsec, &tz, &tzn, DateStyle, buf);
  	else
  		ereport(ERROR,
***************
*** 419,425 ****
  	/* rangecheck: see if timestamptz_out would like it */
  	if (TIMESTAMP_NOT_FINITE(timestamp))
  		 /* ok */ ;
! 	else if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn) !=0)
  		ereport(ERROR,
  				(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
  				 errmsg("timestamp out of range")));
--- 419,425 ----
  	/* rangecheck: see if timestamptz_out would like it */
  	if (TIMESTAMP_NOT_FINITE(timestamp))
  		 /* ok */ ;
! 	else if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn, NULL) !=0)
  		ereport(ERROR,
  				(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
  				 errmsg("timestamp out of range")));
***************
*** 978,986 ****
   * Returns:
   *	 0 on success
   *	-1 on out of range
   */
  int
! timestamp2tm(Timestamp dt, int *tzp, struct pg_tm * tm, fsec_t *fsec, char **tzn)
  {
  	Timestamp date;
  	Timestamp	time;
--- 978,989 ----
   * Returns:
   *	 0 on success
   *	-1 on out of range
+  *
+  * If attimezone is NULL, the global timezone (including possblly brute forced
+  * timezone) will be used.
   */
  int
! timestamp2tm(Timestamp dt, int *tzp, struct pg_tm * tm, fsec_t *fsec, char **tzn, pg_tz *attimezone)
  {
  	Timestamp date;
  	Timestamp	time;
***************
*** 991,997 ****
  	 * specified. Go ahead and rotate to the local time zone since we will
  	 * later bypass any calls which adjust the tm fields.
  	 */
! 	if (HasCTZSet && (tzp != NULL))
  	{
  #ifdef HAVE_INT64_TIMESTAMP
  		dt -= CTimeZone * USECS_PER_SEC;
--- 994,1000 ----
  	 * specified. Go ahead and rotate to the local time zone since we will
  	 * later bypass any calls which adjust the tm fields.
  	 */
! 	if ((attimezone==NULL) && HasCTZSet && (tzp != NULL))
  	{
  #ifdef HAVE_INT64_TIMESTAMP
  		dt -= CTimeZone * USECS_PER_SEC;
***************
*** 1044,1050 ****
  	 * We have a brute force time zone per SQL99? Then use it without
  	 * change since we have already rotated to the time zone.
  	 */
! 	if (HasCTZSet)
  	{
  		*tzp = CTimeZone;
  		tm->tm_isdst = 0;
--- 1047,1053 ----
  	 * We have a brute force time zone per SQL99? Then use it without
  	 * change since we have already rotated to the time zone.
  	 */
! 	if ((attimezone==NULL) && HasCTZSet)
  	{
  		*tzp = CTimeZone;
  		tm->tm_isdst = 0;
***************
*** 1075,1081 ****
  	utime = (pg_time_t) dt;
  	if ((Timestamp) utime == dt)
  	{
! 		struct pg_tm *tx = pg_localtime(&utime, global_timezone);
  
  		tm->tm_year = tx->tm_year + 1900;
  		tm->tm_mon = tx->tm_mon + 1;
--- 1078,1084 ----
  	utime = (pg_time_t) dt;
  	if ((Timestamp) utime == dt)
  	{
! 		struct pg_tm *tx = pg_localtime(&utime, (attimezone!=NULL)?attimezone:global_timezone);
  
  		tm->tm_year = tx->tm_year + 1900;
  		tm->tm_mon = tx->tm_mon + 1;
***************
*** 1920,1926 ****
  					   *tm = &tt;
  			fsec_t		fsec;
  
! 			if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL) !=0)
  				ereport(ERROR,
  						(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
  						 errmsg("timestamp out of range")));
--- 1923,1929 ----
  					   *tm = &tt;
  			fsec_t		fsec;
  
! 			if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) !=0)
  				ereport(ERROR,
  						(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
  						 errmsg("timestamp out of range")));
***************
*** 1999,2005 ****
  					   *tm = &tt;
  			fsec_t		fsec;
  
! 			if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn) !=0)
  				ereport(ERROR,
  						(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
  						 errmsg("timestamp out of range")));
--- 2002,2008 ----
  					   *tm = &tt;
  			fsec_t		fsec;
  
! 			if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn, NULL) !=0)
  				ereport(ERROR,
  						(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
  						 errmsg("timestamp out of range")));
***************
*** 2326,2333 ****
  
  	result = (Interval *) palloc(sizeof(Interval));
  
! 	if (timestamp2tm(dt1, NULL, tm1, &fsec1, NULL) == 0 &&
! 		timestamp2tm(dt2, NULL, tm2, &fsec2, NULL) == 0)
  	{
  		fsec = (fsec1 - fsec2);
  		tm->tm_sec = tm1->tm_sec - tm2->tm_sec;
--- 2329,2336 ----
  
  	result = (Interval *) palloc(sizeof(Interval));
  
! 	if (timestamp2tm(dt1, NULL, tm1, &fsec1, NULL, NULL) == 0 &&
! 		timestamp2tm(dt2, NULL, tm2, &fsec2, NULL, NULL) == 0)
  	{
  		fsec = (fsec1 - fsec2);
  		tm->tm_sec = tm1->tm_sec - tm2->tm_sec;
***************
*** 2440,2447 ****
  
  	result = (Interval *) palloc(sizeof(Interval));
  
! 	if (timestamp2tm(dt1, &tz1, tm1, &fsec1, &tzn) == 0 &&
! 		timestamp2tm(dt2, &tz2, tm2, &fsec2, &tzn) == 0)
  	{
  		fsec = fsec1 - fsec2;
  		tm->tm_sec = tm1->tm_sec - tm2->tm_sec;
--- 2443,2450 ----
  
  	result = (Interval *) palloc(sizeof(Interval));
  
! 	if (timestamp2tm(dt1, &tz1, tm1, &fsec1, &tzn, NULL) == 0 &&
! 		timestamp2tm(dt2, &tz2, tm2, &fsec2, &tzn, NULL) == 0)
  	{
  		fsec = fsec1 - fsec2;
  		tm->tm_sec = tm1->tm_sec - tm2->tm_sec;
***************
*** 2744,2750 ****
  
  	if (type == UNITS)
  	{
! 		if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL) !=0)
  			ereport(ERROR,
  					(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
  					 errmsg("timestamp out of range")));
--- 2747,2753 ----
  
  	if (type == UNITS)
  	{
! 		if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) !=0)
  			ereport(ERROR,
  					(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
  					 errmsg("timestamp out of range")));
***************
*** 2875,2881 ****
  
  	if (type == UNITS)
  	{
! 		if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn) !=0)
  			ereport(ERROR,
  					(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
  					 errmsg("timestamp out of range")));
--- 2878,2884 ----
  
  	if (type == UNITS)
  	{
! 		if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn, NULL) !=0)
  			ereport(ERROR,
  					(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
  					 errmsg("timestamp out of range")));
***************
*** 3265,3271 ****
  
  	if (type == UNITS)
  	{
! 		if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL) !=0)
  			ereport(ERROR,
  					(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
  					 errmsg("timestamp out of range")));
--- 3268,3274 ----
  
  	if (type == UNITS)
  	{
! 		if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) !=0)
  			ereport(ERROR,
  					(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
  					 errmsg("timestamp out of range")));
***************
*** 3399,3405 ****
  					 * convert to timestamptz to produce consistent
  					 * results
  					 */
! 					if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL) !=0)
  						ereport(ERROR,
  						   (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
  							errmsg("timestamp out of range")));
--- 3402,3408 ----
  					 * convert to timestamptz to produce consistent
  					 * results
  					 */
! 					if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) !=0)
  						ereport(ERROR,
  						   (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
  							errmsg("timestamp out of range")));
***************
*** 3419,3425 ****
  					break;
  				}
  			case DTK_DOW:
! 				if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL) !=0)
  					ereport(ERROR,
  							(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
  							 errmsg("timestamp out of range")));
--- 3422,3428 ----
  					break;
  				}
  			case DTK_DOW:
! 				if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) !=0)
  					ereport(ERROR,
  							(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
  							 errmsg("timestamp out of range")));
***************
*** 3427,3433 ****
  				break;
  
  			case DTK_DOY:
! 				if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL) !=0)
  					ereport(ERROR,
  							(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
  							 errmsg("timestamp out of range")));
--- 3430,3436 ----
  				break;
  
  			case DTK_DOY:
! 				if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) !=0)
  					ereport(ERROR,
  							(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
  							 errmsg("timestamp out of range")));
***************
*** 3490,3496 ****
  
  	if (type == UNITS)
  	{
! 		if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn) !=0)
  			ereport(ERROR,
  					(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
  					 errmsg("timestamp out of range")));
--- 3493,3499 ----
  
  	if (type == UNITS)
  	{
! 		if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn, NULL) !=0)
  			ereport(ERROR,
  					(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
  					 errmsg("timestamp out of range")));
***************
*** 3625,3631 ****
  				break;
  
  			case DTK_DOW:
! 				if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn) !=0)
  					ereport(ERROR,
  							(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
  							 errmsg("timestamp out of range")));
--- 3628,3634 ----
  				break;
  
  			case DTK_DOW:
! 				if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn, NULL) !=0)
  					ereport(ERROR,
  							(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
  							 errmsg("timestamp out of range")));
***************
*** 3633,3639 ****
  				break;
  
  			case DTK_DOY:
! 				if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn) !=0)
  					ereport(ERROR,
  							(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
  							 errmsg("timestamp out of range")));
--- 3636,3642 ----
  				break;
  
  			case DTK_DOY:
! 				if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn, NULL) !=0)
  					ereport(ERROR,
  							(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
  							 errmsg("timestamp out of range")));
***************
*** 3809,3846 ****
  {
  	text	   *zone = PG_GETARG_TEXT_P(0);
  	Timestamp timestamp = PG_GETARG_TIMESTAMP(1);
! 	TimestampTz result;
  	int			tz;
! 	int			type,
! 				val;
! 	char	   *lowzone;
  
  	if (TIMESTAMP_NOT_FINITE(timestamp))
  		PG_RETURN_TIMESTAMPTZ(timestamp);
  
! 	lowzone = downcase_truncate_identifier(VARDATA(zone),
! 										   VARSIZE(zone) - VARHDRSZ,
! 										   false);
! 
! 	type = DecodeSpecial(0, lowzone, &val);
! 
! 	if (type == TZ || type == DTZ)
! 	{
! 		tz = -(val * 60);
! 
! 		result = dt2local(timestamp, tz);
! 	}
! 	else
! 	{
  		ereport(ERROR,
  				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
! 				 errmsg("time zone \"%s\" not recognized",
! 						lowzone)));
! 
  		PG_RETURN_NULL();
  	}
  
! 	PG_RETURN_TIMESTAMPTZ(result);
  }	/* timestamp_zone() */
  
  /* timestamp_izone()
--- 3812,3851 ----
  {
  	text	   *zone = PG_GETARG_TEXT_P(0);
  	Timestamp timestamp = PG_GETARG_TIMESTAMP(1);
! 	Timestamp result;
  	int			tz;
! 	pg_tz      *tzp;
! 	char        tzname[TZ_STRLEN_MAX+1];
! 	int         len;
! 	struct pg_tm tm;
! 	fsec_t      fsec;
  
  	if (TIMESTAMP_NOT_FINITE(timestamp))
  		PG_RETURN_TIMESTAMPTZ(timestamp);
  
! 	/* Find the specified timezone? */
! 	len = (VARSIZE(zone)-VARHDRSZ>TZ_STRLEN_MAX)?TZ_STRLEN_MAX:(VARSIZE(zone)-VARHDRSZ);
! 	memcpy(tzname,VARDATA(zone),len);
! 	tzname[len] = 0;
! 	tzp = pg_tzset(tzname);
! 	if (!tzp) {
  		ereport(ERROR,
  				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
! 				 errmsg("time zone \"%s\" not recognised",
! 				        tzname)));
  		PG_RETURN_NULL();
  	}
  
! 	/* Apply the timezone change */
! 	if (timestamp2tm(timestamp, &tz, &tm, &fsec, NULL, tzp) != 0 ||
! 	    tm2timestamp(&tm, fsec, NULL, &result) != 0) {
! 		ereport(ERROR,
! 				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
! 				 errmsg("could not convert to time zone \"%s\"",
! 				        tzname)));
! 		PG_RETURN_NULL();
! 	}
! 	PG_RETURN_TIMESTAMPTZ(timestamp2timestamptz(result));
  }	/* timestamp_zone() */
  
  /* timestamp_izone()
***************
*** 3900,3906 ****
  
  	else
  	{
! 		if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL) !=0)
  			ereport(ERROR,
  					(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
  					 errmsg("timestamp out of range")));
--- 3905,3911 ----
  
  	else
  	{
! 		if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) !=0)
  			ereport(ERROR,
  					(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
  					 errmsg("timestamp out of range")));
***************
*** 3935,3941 ****
  
  	else
  	{
! 		if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn) !=0)
  			ereport(ERROR,
  					(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
  					 errmsg("timestamp out of range")));
--- 3940,3946 ----
  
  	else
  	{
! 		if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn, NULL) !=0)
  			ereport(ERROR,
  					(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
  					 errmsg("timestamp out of range")));
***************
*** 3944,3950 ****
  					(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
  					 errmsg("timestamp out of range")));
  	}
- 
  	PG_RETURN_TIMESTAMP(result);
  }
  
--- 3949,3954 ----
***************
*** 3960,3990 ****
  	Timestamp	result;
  
  	int			tz;
! 	int			type,
! 				val;
! 	char	   *lowzone;
  
  	if (TIMESTAMP_NOT_FINITE(timestamp))
  		PG_RETURN_NULL();
  
! 	lowzone = downcase_truncate_identifier(VARDATA(zone),
! 										   VARSIZE(zone) - VARHDRSZ,
! 										   false);
! 
! 	type = DecodeSpecial(0, lowzone, &val);
  
! 	if (type == TZ || type == DTZ)
! 	{
! 		tz = val * 60;
  
! 		result = dt2local(timestamp, tz);
  	}
- 	else
- 	{
- 		ereport(ERROR,
- 				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- 				 errmsg("time zone \"%s\" not recognized", lowzone)));
  
  		PG_RETURN_NULL();
  	}
  
--- 3964,3997 ----
  	Timestamp	result;
  
  	int			tz;
! 	pg_tz	   *tzp;
! 	char        tzname[TZ_STRLEN_MAX];
! 	int         len;
! 	struct pg_tm tm;
! 	fsec_t      fsec = 0;
  
  	if (TIMESTAMP_NOT_FINITE(timestamp))
  		PG_RETURN_NULL();
  
! 	/* Find the specified zone */
! 	len = (VARSIZE(zone)-VARHDRSZ>TZ_STRLEN_MAX)?TZ_STRLEN_MAX:(VARSIZE(zone)-VARHDRSZ);
! 	memcpy(tzname,VARDATA(zone),len);
! 	tzname[len] = 0;
! 	tzp = pg_tzset(tzname);
  
! 	if (!tzp) {
! 		ereport(ERROR,
! 			(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
! 			 errmsg("time zone \"%s\" not recognized", tzname)));
  
! 		PG_RETURN_NULL();
  	}
  
+ 	if (timestamp2tm(timestamp, &tz, &tm, &fsec, NULL, tzp) != 0 ||
+ 	    tm2timestamp(&tm, fsec, NULL, &result)) { 
+ 		ereport(ERROR,
+ 			(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ 			errmsg("could not to convert to time zone \"%s\"", tzname)));
  		PG_RETURN_NULL();
  	}
  
Index: src/include/pgtime.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/pgtime.h,v
retrieving revision 1.7
diff -c -r1.7 pgtime.h
*** src/include/pgtime.h	19 Apr 2005 03:13:59 -0000	1.7
--- src/include/pgtime.h	6 Jun 2005 17:30:30 -0000
***************
*** 57,60 ****
--- 57,64 ----
  extern const char *pg_get_timezone_name(pg_tz *tz);
  
  extern pg_tz *global_timezone;
+ 
+ /* Maximum length of a timezone name */
+ #define TZ_STRLEN_MAX 255
+ 
  #endif   /* _PGTIME_H */
Index: src/include/utils/timestamp.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/utils/timestamp.h,v
retrieving revision 1.43
diff -c -r1.43 timestamp.h
*** src/include/utils/timestamp.h	25 May 2005 21:40:42 -0000	1.43
--- src/include/utils/timestamp.h	6 Jun 2005 17:30:32 -0000
***************
*** 260,266 ****
  
  extern int	tm2timestamp(struct pg_tm * tm, fsec_t fsec, int *tzp, Timestamp *dt);
  extern int timestamp2tm(Timestamp dt, int *tzp, struct pg_tm * tm,
! 			 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 pg_tm * tm, fsec_t *fsec);
--- 260,266 ----
  
  extern int	tm2timestamp(struct pg_tm * tm, fsec_t fsec, int *tzp, Timestamp *dt);
  extern int timestamp2tm(Timestamp dt, int *tzp, struct pg_tm * tm,
! 			 fsec_t *fsec, char **tzn, pg_tz *attimezone);
  extern void dt2time(Timestamp dt, int *hour, int *min, int *sec, fsec_t *fsec);
  
  extern int	interval2tm(Interval span, struct pg_tm * tm, fsec_t *fsec);
Index: src/timezone/pgtz.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/timezone/pgtz.h,v
retrieving revision 1.11
diff -c -r1.11 pgtz.h
*** src/timezone/pgtz.h	19 Apr 2005 03:13:59 -0000	1.11
--- src/timezone/pgtz.h	6 Jun 2005 17:30:33 -0000
***************
*** 18,25 ****
  
  #include "tzfile.h"
  
- #define TZ_STRLEN_MAX 255
- 
  extern char *pg_TZDIR(void);
  
  #define BIGGEST(a, b)	(((a) > (b)) ? (a) : (b))
--- 18,23 ----
