aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/utils/adt/datetime.c46
-rw-r--r--src/include/pgtime.h3
-rw-r--r--src/include/utils/datetime.h4
-rw-r--r--src/timezone/localtime.c27
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 *