Index: src/backend/utils/adt/date.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/utils/adt/date.c,v
retrieving revision 1.118
diff -c -c -r1.118 date.c
*** src/backend/utils/adt/date.c	22 Jul 2005 05:03:09 -0000	1.118
--- src/backend/utils/adt/date.c	23 Jul 2005 14:23:14 -0000
***************
*** 301,307 ****
  	tm->tm_hour = 0;
  	tm->tm_min = 0;
  	tm->tm_sec = 0;
! 	tz = DetermineLocalTimeZone(tm);
  
  #ifdef HAVE_INT64_TIMESTAMP
  	result = dateVal * USECS_PER_DAY + tz * USECS_PER_SEC;
--- 301,307 ----
  	tm->tm_hour = 0;
  	tm->tm_min = 0;
  	tm->tm_sec = 0;
! 	tz = DetermineTimeZoneOffset(tm, global_timezone);
  
  #ifdef HAVE_INT64_TIMESTAMP
  	result = dateVal * USECS_PER_DAY + tz * USECS_PER_SEC;
***************
*** 2231,2237 ****
  
  	GetCurrentDateTime(tm);
  	time2tm(time, tm, &fsec);
! 	tz = DetermineLocalTimeZone(tm);
  
  	result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
  
--- 2231,2237 ----
  
  	GetCurrentDateTime(tm);
  	time2tm(time, tm, &fsec);
! 	tz = DetermineTimeZoneOffset(tm, global_timezone);
  
  	result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
  
Index: src/backend/utils/adt/datetime.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v
retrieving revision 1.156
diff -c -c -r1.156 datetime.c
*** src/backend/utils/adt/datetime.c	22 Jul 2005 03:46:33 -0000	1.156
--- src/backend/utils/adt/datetime.c	23 Jul 2005 14:23:15 -0000
***************
*** 1612,1618 ****
  			if (fmask & DTK_M(DTZMOD))
  				return DTERR_BAD_FORMAT;
  
! 			*tzp = DetermineLocalTimeZone(tm);
  		}
  	}
  
--- 1612,1618 ----
  			if (fmask & DTK_M(DTZMOD))
  				return DTERR_BAD_FORMAT;
  
! 			*tzp = DetermineTimeZoneOffset(tm, global_timezone);
  		}
  	}
  
***************
*** 1620,1629 ****
  }
  
  
! /* DetermineLocalTimeZone()
   *
   * Given a struct pg_tm in which tm_year, tm_mon, tm_mday, tm_hour, tm_min, and
!  * tm_sec fields are set, attempt to determine the applicable local zone
   * (ie, regular or daylight-savings time) at that time.  Set the struct pg_tm's
   * tm_isdst field accordingly, and return the actual timezone offset.
   *
--- 1620,1629 ----
  }
  
  
! /* DetermineTimeZoneOffset()
   *
   * Given a struct pg_tm in which tm_year, tm_mon, tm_mday, tm_hour, tm_min, and
!  * tm_sec fields are set, attempt to determine the applicable time zone
   * (ie, regular or daylight-savings time) at that time.  Set the struct pg_tm's
   * tm_isdst field accordingly, and return the actual timezone offset.
   *
***************
*** 1632,1638 ****
   * of mktime(), anyway.
   */
  int
! DetermineLocalTimeZone(struct pg_tm *tm)
  {
  	int			date,
  				sec;
--- 1632,1638 ----
   * of mktime(), anyway.
   */
  int
! DetermineTimeZoneOffset(struct pg_tm *tm, pg_tz *tzp)
  {
  	int			date,
  				sec;
***************
*** 1648,1654 ****
  				after_isdst;
  	int			res;
  
! 	if (HasCTZSet)
  	{
  		tm->tm_isdst = 0;		/* for lack of a better idea */
  		return CTimeZone;
--- 1648,1654 ----
  				after_isdst;
  	int			res;
  
! 	if (tzp == global_timezone && HasCTZSet)
  	{
  		tm->tm_isdst = 0;		/* for lack of a better idea */
  		return CTimeZone;
***************
*** 1687,1693 ****
  							   &before_gmtoff, &before_isdst,
  							   &boundary,
  							   &after_gmtoff, &after_isdst,
! 		                       global_timezone);
  	if (res < 0)
  		goto overflow;			/* failure? */
  
--- 1687,1693 ----
  							   &before_gmtoff, &before_isdst,
  							   &boundary,
  							   &after_gmtoff, &after_isdst,
! 		                       tzp);
  	if (res < 0)
  		goto overflow;			/* failure? */
  
***************
*** 2282,2288 ****
  		tmp->tm_hour = tm->tm_hour;
  		tmp->tm_min = tm->tm_min;
  		tmp->tm_sec = tm->tm_sec;
! 		*tzp = DetermineLocalTimeZone(tmp);
  		tm->tm_isdst = tmp->tm_isdst;
  	}
  
--- 2282,2288 ----
  		tmp->tm_hour = tm->tm_hour;
  		tmp->tm_min = tm->tm_min;
  		tmp->tm_sec = tm->tm_sec;
! 		*tzp = DetermineTimeZoneOffset(tmp, global_timezone);
  		tm->tm_isdst = tmp->tm_isdst;
  	}
  
Index: src/backend/utils/adt/formatting.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/utils/adt/formatting.c,v
retrieving revision 1.92
diff -c -c -r1.92 formatting.c
*** src/backend/utils/adt/formatting.c	21 Jul 2005 03:56:16 -0000	1.92
--- src/backend/utils/adt/formatting.c	23 Jul 2005 14:23:17 -0000
***************
*** 2989,2995 ****
  
  	do_to_timestamp(date_txt, fmt, &tm, &fsec);
  
! 	tz = DetermineLocalTimeZone(&tm);
  
  	if (tm2timestamp(&tm, fsec, &tz, &result) != 0)
  		ereport(ERROR,
--- 2989,2995 ----
  
  	do_to_timestamp(date_txt, fmt, &tm, &fsec);
  
! 	tz = DetermineTimeZoneOffset(&tm, global_timezone);
  
  	if (tm2timestamp(&tm, fsec, &tz, &result) != 0)
  		ereport(ERROR,
Index: src/backend/utils/adt/nabstime.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/utils/adt/nabstime.c,v
retrieving revision 1.141
diff -c -c -r1.141 nabstime.c
*** src/backend/utils/adt/nabstime.c	22 Jul 2005 19:55:50 -0000	1.141
--- src/backend/utils/adt/nabstime.c	23 Jul 2005 14:23:18 -0000
***************
*** 474,480 ****
  		result = NOEND_ABSTIME;
  	else if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) == 0)
  	{
! 		tz = DetermineLocalTimeZone(tm);
  		result = tm2abstime(tm, tz);
  	}
  	else
--- 474,480 ----
  		result = NOEND_ABSTIME;
  	else if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) == 0)
  	{
! 		tz = DetermineTimeZoneOffset(tm, global_timezone);
  		result = tm2abstime(tm, tz);
  	}
  	else
Index: src/backend/utils/adt/timestamp.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/utils/adt/timestamp.c,v
retrieving revision 1.143
diff -c -c -r1.143 timestamp.c
*** src/backend/utils/adt/timestamp.c	23 Jul 2005 02:02:27 -0000	1.143
--- src/backend/utils/adt/timestamp.c	23 Jul 2005 14:23:19 -0000
***************
*** 2100,2106 ****
  			if (tm->tm_mday > day_tab[isleap(tm->tm_year)][tm->tm_mon - 1])
  				tm->tm_mday = (day_tab[isleap(tm->tm_year)][tm->tm_mon - 1]);
  
! 			tz = DetermineLocalTimeZone(tm);
  
  			if (tm2timestamp(tm, fsec, &tz, &timestamp) != 0)
  				ereport(ERROR,
--- 2100,2106 ----
  			if (tm->tm_mday > day_tab[isleap(tm->tm_year)][tm->tm_mon - 1])
  				tm->tm_mday = (day_tab[isleap(tm->tm_year)][tm->tm_mon - 1]);
  
! 			tz = DetermineTimeZoneOffset(tm, global_timezone);
  
  			if (tm2timestamp(tm, fsec, &tz, &timestamp) != 0)
  				ereport(ERROR,
***************
*** 2124,2130 ****
  			julian = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) + span->day;
  			j2date(julian, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
  
! 			tz = DetermineLocalTimeZone(tm);
  
  			if (tm2timestamp(tm, fsec, &tz, &timestamp) != 0)
  				ereport(ERROR,
--- 2124,2130 ----
  			julian = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) + span->day;
  			j2date(julian, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
  
! 			tz = DetermineTimeZoneOffset(tm, global_timezone);
  
  			if (tm2timestamp(tm, fsec, &tz, &timestamp) != 0)
  				ereport(ERROR,
***************
*** 3104,3110 ****
  		}
  
  		if (redotz)
! 			tz = DetermineLocalTimeZone(tm);
  
  		if (tm2timestamp(tm, fsec, &tz, &result) != 0)
  			ereport(ERROR,
--- 3104,3110 ----
  		}
  
  		if (redotz)
! 			tz = DetermineTimeZoneOffset(tm, global_timezone);
  
  		if (tm2timestamp(tm, fsec, &tz, &result) != 0)
  			ereport(ERROR,
***************
*** 3529,3535 ****
  						   (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
  							errmsg("timestamp out of range")));
  
! 					tz = DetermineLocalTimeZone(tm);
  
  					if (tm2timestamp(tm, fsec, &tz, &timestamptz) != 0)
  						ereport(ERROR,
--- 3529,3535 ----
  						   (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
  							errmsg("timestamp out of range")));
  
! 					tz = DetermineTimeZoneOffset(tm, global_timezone);
  
  					if (tm2timestamp(tm, fsec, &tz, &timestamptz) != 0)
  						ereport(ERROR,
***************
*** 3924,3935 ****
  
  /* 	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.
!  *	This function is tricky because instead of shifting
!  *	the time _to_ a new time zone, it sets the time to _be_
!  *	the specified timezone.  This requires trickery
!  *	of double-subtracting the requested timezone offset.
   */
  Datum
  timestamp_zone(PG_FUNCTION_ARGS)
--- 3924,3934 ----
  
  /* 	timestamp_zone()
   * 	Encode timestamp type with specified time zone.
!  * 	This function is just timestamp2timestamptz() except instead of
!  *	shifting to the global timezone, we shift to the specified timezone.
!  *	This is different from the other AT TIME ZONE cases because instead
!  *	of shifting to a _to_ a new time zone, it sets the time to _be_ the
!  *	specified timezone.
   */
  Datum
  timestamp_zone(PG_FUNCTION_ARGS)
***************
*** 3943,3953 ****
  	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);
--- 3942,3953 ----
  	int         len;
  	struct pg_tm tm;
  	fsec_t      fsec;
! 	bool		fail;
! 	
  	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);
***************
*** 3963,3970 ****
  	}
  
  	/* Apply the timezone change */
! 	if (timestamp2tm(timestamp, &tz, &tm, &fsec, NULL, tzp) != 0 ||
! 	    tm2timestamp(&tm, fsec, &tz, &result) != 0)
  	{
  		ereport(ERROR,
  				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
--- 3963,3975 ----
  	}
  
  	/* Apply the timezone change */
! 	fail = (timestamp2tm(timestamp, NULL, &tm, &fsec, NULL, tzp) != 0);
! 	if (!fail)
! 	{
! 		tz = DetermineTimeZoneOffset(&tm, tzp);
! 		fail = (tm2timestamp(&tm, fsec, &tz, &result) != 0);
! 	}
! 	if (fail)
  	{
  		ereport(ERROR,
  				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
***************
*** 3972,3979 ****
  				        tzname)));
  		PG_RETURN_NULL();
  	}
- 	/* Must double-adjust for timezone */
- 	result = dt2local(result, -tz);
  
  	PG_RETURN_TIMESTAMPTZ(result);
  }
--- 3977,3982 ----
***************
*** 4039,4045 ****
  					(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
  					 errmsg("timestamp out of range")));
  
! 		tz = DetermineLocalTimeZone(tm);
  
  		if (tm2timestamp(tm, fsec, &tz, &result) != 0)
  			ereport(ERROR,
--- 4042,4048 ----
  					(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
  					 errmsg("timestamp out of range")));
  
! 		tz = DetermineTimeZoneOffset(tm, global_timezone);
  
  		if (tm2timestamp(tm, fsec, &tz, &result) != 0)
  			ereport(ERROR,
Index: src/include/utils/datetime.h
===================================================================
RCS file: /cvsroot/pgsql/src/include/utils/datetime.h,v
retrieving revision 1.55
diff -c -c -r1.55 datetime.h
*** src/include/utils/datetime.h	22 Jul 2005 03:46:34 -0000	1.55
--- src/include/utils/datetime.h	23 Jul 2005 14:23:20 -0000
***************
*** 291,297 ****
  extern void DateTimeParseError(int dterr, const char *str,
  				   const char *datatype);
  
! extern int	DetermineLocalTimeZone(struct pg_tm *tm);
  
  extern int	EncodeDateOnly(struct pg_tm *tm, int style, char *str);
  extern int	EncodeTimeOnly(struct pg_tm *tm, fsec_t fsec, int *tzp, int style, char *str);
--- 291,297 ----
  extern void DateTimeParseError(int dterr, const char *str,
  				   const char *datatype);
  
! extern int	DetermineTimeZoneOffset(struct pg_tm *tm, pg_tz *tzp);
  
  extern int	EncodeDateOnly(struct pg_tm *tm, int style, char *str);
  extern int	EncodeTimeOnly(struct pg_tm *tm, fsec_t fsec, int *tzp, int style, char *str);
