diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index e647ac05ff5d809c1561e5e504a5c480dbc3e3ee..b6af6e7e2531300a6ccb887465fc3a26a982eb56 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -327,6 +327,7 @@ check_timezone(char **newval, void **extra, GucSource source)
 #else
 		myextra.CTimeZone = -interval->time;
 #endif
+		myextra.session_timezone = pg_tzset_offset(myextra.CTimeZone);
 		myextra.HasCTZSet = true;
 
 		pfree(interval);
@@ -341,6 +342,7 @@ check_timezone(char **newval, void **extra, GucSource source)
 		{
 			/* 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 48bf3db9b2c896f1690e488741b74bd2d9ca4d67..1b8f109992a191e0f8ea58bd335833dadcaa5745 100644
--- a/src/backend/utils/adt/datetime.c
+++ b/src/backend/utils/adt/datetime.c
@@ -1465,12 +1465,6 @@ DetermineTimeZoneOffset(struct pg_tm * tm, pg_tz *tzp)
 				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
diff --git a/src/include/pgtime.h b/src/include/pgtime.h
index 57af51e6bd530ee130370ddb366b1f5e5835909c..73a0ed2db719baaf29c01fca4f47da7e5d6e8915 100644
--- a/src/include/pgtime.h
+++ b/src/include/pgtime.h
@@ -68,6 +68,7 @@ extern pg_tz *log_timezone;
 
 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 553a158e2c79fed6358684eb767e0fa2d43b555c..2666deea88bd9838f48f2037378d31bc1b26f8fe 100644
--- a/src/test/regress/expected/horology.out
+++ b/src/test/regress/expected/horology.out
@@ -2935,3 +2935,33 @@ DETAIL:  Value must be an integer.
 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 ea794ecdd935f64a57ae462c867c6263dd6d8f2f..fe9a520cb91437638c6cf50f5ccd1a47607aae0b 100644
--- a/src/test/regress/sql/horology.sql
+++ b/src/test/regress/sql/horology.sql
@@ -461,3 +461,19 @@ SELECT to_timestamp('199711xy', 'YYYYMMDD');
 
 -- 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 203bda88c451fb8558383f9b882c448c92fb5b0a..1130de9a961064f79e0f5ce2fb1a5d602f1ae0ef 100644
--- a/src/timezone/pgtz.c
+++ b/src/timezone/pgtz.c
@@ -288,6 +288,46 @@ pg_tzset(const char *name)
 	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