aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/src/sgml/datatype.sgml23
-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
5 files changed, 77 insertions, 26 deletions
diff --git a/doc/src/sgml/datatype.sgml b/doc/src/sgml/datatype.sgml
index 2cc9770f65e..4b3c1bca19f 100644
--- a/doc/src/sgml/datatype.sgml
+++ b/doc/src/sgml/datatype.sgml
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/datatype.sgml,v 1.178 2006/10/17 21:03:20 tgl Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/datatype.sgml,v 1.179 2006/10/18 16:43:13 tgl Exp $ -->
<chapter id="datatype">
<title id="datatype-title">Data Types</title>
@@ -1356,8 +1356,8 @@ SELECT b, char_length(b) FROM test2;
<entry><type>time [ (<replaceable>p</replaceable>) ] with time zone</type></entry>
<entry>12 bytes</entry>
<entry>times of day only, with time zone</entry>
- <entry>00:00:00+1359</entry>
- <entry>24:00:00-1359</entry>
+ <entry>00:00:00+1459</entry>
+ <entry>24:00:00-1459</entry>
<entry>1 microsecond / 14 digits</entry>
</row>
</tbody>
@@ -1594,7 +1594,8 @@ SELECT b, char_length(b) FROM test2;
and <xref linkend="datatype-timezone-table">.) If a time zone is
specified in the input for <type>time without time zone</type>,
it is silently ignored. You can also specify a date but it will
- be ignored, except when you use a full time zone name like
+ be ignored, except when you use a time zone name that involves a
+ daylight-savings rule, such as
<literal>America/New_York</literal>. In this case specifying the date
is required in order to determine whether standard or daylight-savings
time applies. The appropriate time zone offset is recorded in the
@@ -1747,12 +1748,7 @@ SELECT b, char_length(b) FROM test2;
</programlisting>
are valid values, which follow the <acronym>ISO</acronym> 8601
- standard. You can also specify the full time zone name as in
-<programlisting>
-1999-01-08 04:05:06 America/New_York
-</programlisting>
-
- In addition, the wide-spread format
+ standard. In addition, the wide-spread format
<programlisting>
January 8 04:05:06 1999 PST
</programlisting>
@@ -2210,12 +2206,7 @@ January 8 04:05:06 1999 PST
There is a conceptual and practical difference between the abbreviations
and the full names: abbreviations always represent a fixed offset from
UTC, whereas most of the full names imply a local daylight-savings time
- rule and so have two possible UTC offsets. That's why you always have to
- specify a date if you want to use full time zone names in <type>timetz</>
- values. This is also the reason why you should set <xref
- linkend="guc-timezone"> to a full time zone name: this way,
- <productname>PostgreSQL</productname>
- will always know the correct UTC offset for your region.
+ rule and so have two possible UTC offsets.
</para>
<para>
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 *