diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2006-10-18 16:43:14 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2006-10-18 16:43:14 +0000 |
commit | 877f08da14719a1bead6154785ab45714d347998 (patch) | |
tree | fe730f9ddff1b81fb8d28d97924d1f81565d8370 /src | |
parent | 723f716be04c3e59bb7fdaa6ff044bda6ea4f94b (diff) | |
download | postgresql-877f08da14719a1bead6154785ab45714d347998.tar.gz postgresql-877f08da14719a1bead6154785ab45714d347998.zip |
Fix up timetz input so that a date is required only when the specified
timezone actually has a daylight-savings rule. This avoids breaking
cases that used to work because they went through the DecodePosixTimezone
code path. Per contrib regression failures (mea culpa for not running
those yesterday...). Also document the already-applied change to allow
GMT offsets up to 14 hours.
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/utils/adt/datetime.c | 46 | ||||
-rw-r--r-- | src/include/pgtime.h | 3 | ||||
-rw-r--r-- | src/include/utils/datetime.h | 4 | ||||
-rw-r--r-- | src/timezone/localtime.c | 27 |
4 files changed, 70 insertions, 10 deletions
diff --git a/src/backend/utils/adt/datetime.c b/src/backend/utils/adt/datetime.c index cfb29dce568..f72d1c6b403 100644 --- a/src/backend/utils/adt/datetime.c +++ b/src/backend/utils/adt/datetime.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/adt/datetime.c,v 1.173 2006/10/17 21:03:21 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/datetime.c,v 1.174 2006/10/18 16:43:13 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1199,6 +1199,18 @@ DecodeDateTime(char **field, int *ftype, int nf, ptype = val; break; + case UNKNOWN_FIELD: + /* + * Before giving up and declaring error, check to see + * if it is an all-alpha timezone name. + */ + namedTz = pg_tzset(field[i]); + if (!namedTz) + return DTERR_BAD_FORMAT; + /* we'll apply the zone setting below */ + tmask = DTK_M(TZ); + break; + default: return DTERR_BAD_FORMAT; } @@ -1911,6 +1923,18 @@ DecodeTimeOnly(char **field, int *ftype, int nf, ptype = val; break; + case UNKNOWN_FIELD: + /* + * Before giving up and declaring error, check to see + * if it is an all-alpha timezone name. + */ + namedTz = pg_tzset(field[i]); + if (!namedTz) + return DTERR_BAD_FORMAT; + /* we'll apply the zone setting below */ + tmask = DTK_M(TZ); + break; + default: return DTERR_BAD_FORMAT; } @@ -1952,18 +1976,28 @@ DecodeTimeOnly(char **field, int *ftype, int nf, /* * If we had a full timezone spec, compute the offset (we could not - * do it before, because we need the date to resolve DST status). + * do it before, because we may need the date to resolve DST status). */ if (namedTz != NULL) { - /* a date has to be specified */ - if ((fmask & DTK_DATE_M) != DTK_DATE_M) - return DTERR_BAD_FORMAT; + long int gmtoff; + /* daylight savings time modifier disallowed with full TZ */ if (fmask & DTK_M(DTZMOD)) return DTERR_BAD_FORMAT; - *tzp = DetermineTimeZoneOffset(tm, namedTz); + /* if non-DST zone, we do not need to know the date */ + if (pg_get_timezone_offset(namedTz, &gmtoff)) + { + *tzp = -(int) gmtoff; + } + else + { + /* a date has to be specified */ + if ((fmask & DTK_DATE_M) != DTK_DATE_M) + return DTERR_BAD_FORMAT; + *tzp = DetermineTimeZoneOffset(tm, namedTz); + } } /* timezone not specified? then find local timezone if possible */ diff --git a/src/include/pgtime.h b/src/include/pgtime.h index 0e02c9e24b0..bbb83b7fd61 100644 --- a/src/include/pgtime.h +++ b/src/include/pgtime.h @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * * IDENTIFICATION - * $PostgreSQL: pgsql/src/include/pgtime.h,v 1.13 2006/09/16 20:14:33 tgl Exp $ + * $PostgreSQL: pgsql/src/include/pgtime.h,v 1.14 2006/10/18 16:43:14 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -55,6 +55,7 @@ extern size_t pg_strftime(char *s, size_t max, const char *format, extern void pg_timezone_initialize(void); extern pg_tz *pg_tzset(const char *tzname); extern bool tz_acceptable(pg_tz *tz); +extern bool pg_get_timezone_offset(const pg_tz *tz, long int *gmtoff); extern const char *pg_get_timezone_name(pg_tz *tz); extern pg_tzenum *pg_tzenumerate_start(void); diff --git a/src/include/utils/datetime.h b/src/include/utils/datetime.h index 56f018b6ccc..60a7c159a94 100644 --- a/src/include/utils/datetime.h +++ b/src/include/utils/datetime.h @@ -9,7 +9,7 @@ * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/utils/datetime.h,v 1.61 2006/09/16 20:14:33 tgl Exp $ + * $PostgreSQL: pgsql/src/include/utils/datetime.h,v 1.62 2006/10/18 16:43:14 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -176,7 +176,7 @@ #define DTK_DATE_M (DTK_M(YEAR) | DTK_M(MONTH) | DTK_M(DAY)) #define DTK_TIME_M (DTK_M(HOUR) | DTK_M(MINUTE) | DTK_M(SECOND)) -#define MAXDATELEN 51 /* maximum possible length of an input date +#define MAXDATELEN 63 /* maximum possible length of an input date * string (not counting tr. null) */ #define MAXDATEFIELDS 25 /* maximum possible number of fields in a date * string */ diff --git a/src/timezone/localtime.c b/src/timezone/localtime.c index f5c6c0db8df..fca5ebac643 100644 --- a/src/timezone/localtime.c +++ b/src/timezone/localtime.c @@ -3,7 +3,7 @@ * 1996-06-05 by Arthur David Olson (arthur_david_olson@nih.gov). * * IDENTIFICATION - * $PostgreSQL: pgsql/src/timezone/localtime.c,v 1.15 2006/10/16 19:58:26 tgl Exp $ + * $PostgreSQL: pgsql/src/timezone/localtime.c,v 1.16 2006/10/18 16:43:14 tgl Exp $ */ /* @@ -1067,6 +1067,31 @@ pg_next_dst_boundary(const pg_time_t *timep, } /* + * If the given timezone uses only one GMT offset, store that offset + * into *gmtoff and return TRUE, else return FALSE. + */ +bool +pg_get_timezone_offset(const pg_tz *tz, long int *gmtoff) +{ + /* + * The zone could have more than one ttinfo, if it's historically used + * more than one abbreviation. We return TRUE as long as they all have + * the same gmtoff. + */ + const struct state *sp; + int i; + + sp = &tz->state; + for (i = 1; i < sp->typecnt; i++) + { + if (sp->ttis[i].tt_gmtoff != sp->ttis[0].tt_gmtoff) + return false; + } + *gmtoff = sp->ttis[0].tt_gmtoff; + return true; +} + +/* * Return the name of the current timezone */ const char * |