aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/commands/variable.c2
-rw-r--r--src/backend/utils/adt/datetime.c6
-rw-r--r--src/include/pgtime.h1
-rw-r--r--src/test/regress/expected/horology.out30
-rw-r--r--src/test/regress/sql/horology.sql16
-rw-r--r--src/timezone/pgtz.c40
6 files changed, 89 insertions, 6 deletions
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index e647ac05ff5..b6af6e7e253 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 48bf3db9b2c..1b8f109992a 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 57af51e6bd5..73a0ed2db71 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 553a158e2c7..2666deea88b 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 ea794ecdd93..fe9a520cb91 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 203bda88c45..1130de9a961 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