diff options
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 * |