diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index b6af6e7..e1ce6ff 100644
*** a/src/backend/commands/variable.c
--- b/src/backend/commands/variable.c
*************** assign_datestyle(const char *newval, voi
*** 243,276 ****
   * TIMEZONE
   */
  
- typedef struct
- {
- 	pg_tz	   *session_timezone;
- 	int			CTimeZone;
- 	bool		HasCTZSet;
- } timezone_extra;
- 
  /*
   * check_timezone: GUC check_hook for timezone
   */
  bool
  check_timezone(char **newval, void **extra, GucSource source)
  {
! 	timezone_extra myextra;
  	char	   *endptr;
  	double		hours;
  
- 	/*
- 	 * Initialize the "extra" struct that will be passed to assign_timezone.
- 	 * We don't want to change any of the three global variables except as
- 	 * specified by logic below.  To avoid leaking memory during failure
- 	 * returns, we set up the struct contents in a local variable, and only
- 	 * copy it to *extra at the end.
- 	 */
- 	myextra.session_timezone = session_timezone;
- 	myextra.CTimeZone = CTimeZone;
- 	myextra.HasCTZSet = HasCTZSet;
- 
  	if (pg_strncasecmp(*newval, "interval", 8) == 0)
  	{
  		/*
--- 243,259 ----
   * TIMEZONE
   */
  
  /*
   * check_timezone: GUC check_hook for timezone
   */
  bool
  check_timezone(char **newval, void **extra, GucSource source)
  {
! 	pg_tz	   *new_tz;
! 	long		gmtoffset;
  	char	   *endptr;
  	double		hours;
  
  	if (pg_strncasecmp(*newval, "interval", 8) == 0)
  	{
  		/*
*************** check_timezone(char **newval, void **ext
*** 323,334 ****
  
  		/* Here we change from SQL to Unix sign convention */
  #ifdef HAVE_INT64_TIMESTAMP
! 		myextra.CTimeZone = -(interval->time / USECS_PER_SEC);
  #else
! 		myextra.CTimeZone = -interval->time;
  #endif
! 		myextra.session_timezone = pg_tzset_offset(myextra.CTimeZone);
! 		myextra.HasCTZSet = true;
  
  		pfree(interval);
  	}
--- 306,316 ----
  
  		/* Here we change from SQL to Unix sign convention */
  #ifdef HAVE_INT64_TIMESTAMP
! 		gmtoffset = -(interval->time / USECS_PER_SEC);
  #else
! 		gmtoffset = -interval->time;
  #endif
! 		new_tz = pg_tzset_offset(gmtoffset);
  
  		pfree(interval);
  	}
*************** check_timezone(char **newval, void **ext
*** 341,357 ****
  		if (endptr != *newval && *endptr == '\0')
  		{
  			/* Here we change from SQL to Unix sign convention */
! 			myextra.CTimeZone = -hours * SECS_PER_HOUR;
! 			myextra.session_timezone = pg_tzset_offset(myextra.CTimeZone);
! 			myextra.HasCTZSet = true;
  		}
  		else
  		{
  			/*
  			 * Otherwise assume it is a timezone name, and try to load it.
  			 */
- 			pg_tz	   *new_tz;
- 
  			new_tz = pg_tzset(*newval);
  
  			if (!new_tz)
--- 323,336 ----
  		if (endptr != *newval && *endptr == '\0')
  		{
  			/* Here we change from SQL to Unix sign convention */
! 			gmtoffset = -hours * SECS_PER_HOUR;
! 			new_tz = pg_tzset_offset(gmtoffset);
  		}
  		else
  		{
  			/*
  			 * Otherwise assume it is a timezone name, and try to load it.
  			 */
  			new_tz = pg_tzset(*newval);
  
  			if (!new_tz)
*************** check_timezone(char **newval, void **ext
*** 367,406 ****
  				GUC_check_errdetail("PostgreSQL does not support leap seconds.");
  				return false;
  			}
- 
- 			myextra.session_timezone = new_tz;
- 			myextra.HasCTZSet = false;
  		}
  	}
  
  	/*
- 	 * Prepare the canonical string to return.	GUC wants it malloc'd.
- 	 *
- 	 * Note: the result string should be something that we'd accept as input.
- 	 * We use the numeric format for interval cases, because it's simpler to
- 	 * reload.	In the named-timezone case, *newval is already OK and need not
- 	 * be changed; it might not have the canonical casing, but that's taken
- 	 * care of by show_timezone.
- 	 */
- 	if (myextra.HasCTZSet)
- 	{
- 		char	   *result = (char *) malloc(64);
- 
- 		if (!result)
- 			return false;
- 		snprintf(result, 64, "%.5f",
- 				 (double) (-myextra.CTimeZone) / (double) SECS_PER_HOUR);
- 		free(*newval);
- 		*newval = result;
- 	}
- 
- 	/*
  	 * Pass back data for assign_timezone to use
  	 */
! 	*extra = malloc(sizeof(timezone_extra));
  	if (!*extra)
  		return false;
! 	memcpy(*extra, &myextra, sizeof(timezone_extra));
  
  	return true;
  }
--- 346,361 ----
  				GUC_check_errdetail("PostgreSQL does not support leap seconds.");
  				return false;
  			}
  		}
  	}
  
  	/*
  	 * Pass back data for assign_timezone to use
  	 */
! 	*extra = malloc(sizeof(pg_tz *));
  	if (!*extra)
  		return false;
! 	*((pg_tz **) *extra) = new_tz;
  
  	return true;
  }
*************** check_timezone(char **newval, void **ext
*** 411,453 ****
  void
  assign_timezone(const char *newval, void *extra)
  {
! 	timezone_extra *myextra = (timezone_extra *) extra;
! 
! 	session_timezone = myextra->session_timezone;
! 	CTimeZone = myextra->CTimeZone;
! 	HasCTZSet = myextra->HasCTZSet;
  }
  
  /*
   * show_timezone: GUC show_hook for timezone
-  *
-  * We wouldn't need this, except that historically interval values have been
-  * shown without an INTERVAL prefix, so the display format isn't what would
-  * be accepted as input.  Otherwise we could have check_timezone return the
-  * preferred string to begin with.
   */
  const char *
  show_timezone(void)
  {
  	const char *tzn;
  
! 	if (HasCTZSet)
! 	{
! 		Interval	interval;
! 
! 		interval.month = 0;
! 		interval.day = 0;
! #ifdef HAVE_INT64_TIMESTAMP
! 		interval.time = -(CTimeZone * USECS_PER_SEC);
! #else
! 		interval.time = -CTimeZone;
! #endif
! 
! 		tzn = DatumGetCString(DirectFunctionCall1(interval_out,
! 											  IntervalPGetDatum(&interval)));
! 	}
! 	else
! 		tzn = pg_get_timezone_name(session_timezone);
  
  	if (tzn != NULL)
  		return tzn;
--- 366,384 ----
  void
  assign_timezone(const char *newval, void *extra)
  {
! 	session_timezone = *((pg_tz **) extra);
  }
  
  /*
   * show_timezone: GUC show_hook for timezone
   */
  const char *
  show_timezone(void)
  {
  	const char *tzn;
  
! 	/* Always show the zone's canonical name */
! 	tzn = pg_get_timezone_name(session_timezone);
  
  	if (tzn != NULL)
  		return tzn;
*************** check_log_timezone(char **newval, void *
*** 497,503 ****
  	*extra = malloc(sizeof(pg_tz *));
  	if (!*extra)
  		return false;
! 	memcpy(*extra, &new_tz, sizeof(pg_tz *));
  
  	return true;
  }
--- 428,434 ----
  	*extra = malloc(sizeof(pg_tz *));
  	if (!*extra)
  		return false;
! 	*((pg_tz **) *extra) = new_tz;
  
  	return true;
  }
*************** show_log_timezone(void)
*** 519,524 ****
--- 450,456 ----
  {
  	const char *tzn;
  
+ 	/* Always show the zone's canonical name */
  	tzn = pg_get_timezone_name(log_timezone);
  
  	if (tzn != NULL)
diff --git a/src/backend/utils/init/globals.c b/src/backend/utils/init/globals.c
index 33efb3c..e76704f 100644
*** a/src/backend/utils/init/globals.c
--- b/src/backend/utils/init/globals.c
*************** bool		ExitOnAnyError = false;
*** 93,100 ****
  int			DateStyle = USE_ISO_DATES;
  int			DateOrder = DATEORDER_MDY;
  int			IntervalStyle = INTSTYLE_POSTGRES;
- bool		HasCTZSet = false;
- int			CTimeZone = 0;
  
  bool		enableFsync = true;
  bool		allowSystemTableMods = false;
--- 93,98 ----
diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h
index 0aa540a..98ca553 100644
*** a/src/include/miscadmin.h
--- b/src/include/miscadmin.h
*************** extern int	DateOrder;
*** 219,233 ****
  
  extern int	IntervalStyle;
  
- /*
-  * HasCTZSet is true if user has set timezone as a numeric offset from UTC.
-  * If so, CTimeZone is the timezone offset in seconds (using the Unix-ish
-  * sign convention, ie, positive offset is west of UTC, rather than the
-  * SQL-ish convention that positive is east of UTC).
-  */
- extern bool HasCTZSet;
- extern int	CTimeZone;
- 
  #define MAXTZLEN		10		/* max TZ name len, not counting tr. null */
  
  extern bool enableFsync;
--- 219,224 ----
diff --git a/src/test/regress/expected/horology.out b/src/test/regress/expected/horology.out
index 3ed9c8c..87a6951 100644
*** a/src/test/regress/expected/horology.out
--- b/src/test/regress/expected/horology.out
*************** DETAIL:  Value must be in the range -214
*** 2941,2949 ****
  SET TIME ZONE 'America/New_York';
  SET TIME ZONE '-1.5';
  SHOW TIME ZONE;
!        TimeZone       
! ----------------------
!  @ 1 hour 30 mins ago
  (1 row)
  
  SELECT '2012-12-12 12:00'::timestamptz;
--- 2941,2949 ----
  SET TIME ZONE 'America/New_York';
  SET TIME ZONE '-1.5';
  SHOW TIME ZONE;
!     TimeZone    
! ----------------
!  <-01:30>+01:30
  (1 row)
  
  SELECT '2012-12-12 12:00'::timestamptz;
