diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index e647ac0..b6af6e7 100644
*** a/src/backend/commands/variable.c
--- b/src/backend/commands/variable.c
*************** check_timezone(char **newval, void **ext
*** 327,332 ****
--- 327,333 ----
  #else
  		myextra.CTimeZone = -interval->time;
  #endif
+ 		myextra.session_timezone = pg_tzset_offset(myextra.CTimeZone);
  		myextra.HasCTZSet = true;
  
  		pfree(interval);
*************** check_timezone(char **newval, void **ext
*** 341,346 ****
--- 342,348 ----
  		{
  			/* 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
diff --git a/src/backend/utils/adt/datetime.c b/src/backend/utils/adt/datetime.c
index 48bf3db..1b8f109 100644
*** a/src/backend/utils/adt/datetime.c
--- b/src/backend/utils/adt/datetime.c
*************** DetermineTimeZoneOffset(struct pg_tm * t
*** 1465,1476 ****
  				after_isdst;
  	int			res;
  
- 	if (tzp == session_timezone && HasCTZSet)
- 	{
- 		tm->tm_isdst = 0;		/* for lack of a better idea */
- 		return CTimeZone;
- 	}
- 
  	/*
  	 * First, generate the pg_time_t value corresponding to the given
  	 * y/m/d/h/m/s taken as GMT time.  If this overflows, punt and decide the
--- 1465,1470 ----
diff --git a/src/include/pgtime.h b/src/include/pgtime.h
index 57af51e..73a0ed2 100644
*** a/src/include/pgtime.h
--- b/src/include/pgtime.h
*************** extern pg_tz *log_timezone;
*** 68,73 ****
--- 68,74 ----
  
  extern void pg_timezone_initialize(void);
  extern pg_tz *pg_tzset(const char *tzname);
+ extern pg_tz *pg_tzset_offset(long gmtoffset);
  
  extern pg_tzenum *pg_tzenumerate_start(void);
  extern pg_tz *pg_tzenumerate_next(pg_tzenum *dir);
diff --git a/src/test/regress/expected/horology.out b/src/test/regress/expected/horology.out
index 553a158..2666dee 100644
*** a/src/test/regress/expected/horology.out
--- b/src/test/regress/expected/horology.out
*************** DETAIL:  Value must be an integer.
*** 2935,2937 ****
--- 2935,2967 ----
  SELECT to_timestamp('10000000000', 'FMYYYY');
  ERROR:  value for "YYYY" in source string is out of range
  DETAIL:  Value must be in the range -2147483648 to 2147483647.
+ --
+ -- Check behavior with SQL-style fixed-GMT-offset time zone (cf bug #8572)
+ --
+ 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;
+            timestamptz           
+ ---------------------------------
+  Wed Dec 12 12:00:00 2012 -01:30
+ (1 row)
+ 
+ SELECT '2012-12-12 12:00 America/New_York'::timestamptz;
+            timestamptz           
+ ---------------------------------
+  Wed Dec 12 15:30:00 2012 -01:30
+ (1 row)
+ 
+ SELECT to_char('2012-12-12 12:00'::timestamptz, 'YYYY-MM-DD HH:MI:SS TZ');
+        to_char        
+ ----------------------
+  2012-12-12 12:00:00 
+ (1 row)
+ 
+ RESET TIME ZONE;
diff --git a/src/test/regress/sql/horology.sql b/src/test/regress/sql/horology.sql
index ea794ec..fe9a520 100644
*** a/src/test/regress/sql/horology.sql
--- b/src/test/regress/sql/horology.sql
*************** SELECT to_timestamp('199711xy', 'YYYYMMD
*** 461,463 ****
--- 461,479 ----
  
  -- Input that doesn't fit in an int:
  SELECT to_timestamp('10000000000', 'FMYYYY');
+ 
+ --
+ -- Check behavior with SQL-style fixed-GMT-offset time zone (cf bug #8572)
+ --
+ 
+ SET TIME ZONE 'America/New_York';
+ SET TIME ZONE '-1.5';
+ 
+ SHOW TIME ZONE;
+ 
+ SELECT '2012-12-12 12:00'::timestamptz;
+ SELECT '2012-12-12 12:00 America/New_York'::timestamptz;
+ 
+ SELECT to_char('2012-12-12 12:00'::timestamptz, 'YYYY-MM-DD HH:MI:SS TZ');
+ 
+ RESET TIME ZONE;
diff --git a/src/timezone/pgtz.c b/src/timezone/pgtz.c
index 203bda8..1130de9 100644
*** a/src/timezone/pgtz.c
--- b/src/timezone/pgtz.c
*************** pg_tzset(const char *name)
*** 288,293 ****
--- 288,333 ----
  	return &tzp->tz;
  }
  
+ /*
+  * Load a fixed-GMT-offset timezone.
+  * This is used for SQL-spec SET TIME ZONE INTERVAL 'foo' cases.
+  * It's otherwise equivalent to pg_tzset().
+  *
+  * The GMT offset is specified in seconds, positive values meaning west of
+  * Greenwich (ie, POSIX not ISO sign convention).  However, we use ISO
+  * sign convention in the displayable abbreviation for the zone.
+  */
+ pg_tz *
+ pg_tzset_offset(long gmtoffset)
+ {
+ 	long		absoffset = (gmtoffset < 0) ? -gmtoffset : gmtoffset;
+ 	char		offsetstr[64];
+ 	char		tzname[128];
+ 
+ 	snprintf(offsetstr, sizeof(offsetstr),
+ 			 "%02ld", absoffset / SECSPERHOUR);
+ 	absoffset %= SECSPERHOUR;
+ 	if (absoffset != 0)
+ 	{
+ 		snprintf(offsetstr + strlen(offsetstr),
+ 				 sizeof(offsetstr) - strlen(offsetstr),
+ 				 ":%02ld", absoffset / SECSPERMIN);
+ 		absoffset %= SECSPERMIN;
+ 		if (absoffset != 0)
+ 			snprintf(offsetstr + strlen(offsetstr),
+ 					 sizeof(offsetstr) - strlen(offsetstr),
+ 					 ":%02ld", absoffset);
+ 	}
+ 	if (gmtoffset > 0)
+ 		snprintf(tzname, sizeof(tzname), "<-%s>+%s",
+ 				 offsetstr, offsetstr);
+ 	else
+ 		snprintf(tzname, sizeof(tzname), "<+%s>-%s",
+ 				 offsetstr, offsetstr);
+ 
+ 	return pg_tzset(tzname);
+ }
+ 
  
  /*
   * Initialize timezone library
