diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml
index cc42c5906ff..cf5d3f3b855 100644
--- a/doc/src/sgml/catalogs.sgml
+++ b/doc/src/sgml/catalogs.sgml
@@ -1,4 +1,4 @@
-
+
@@ -4559,6 +4559,11 @@
tables
+
+ pg_timezonenames
+ time zone abbreviations
+
+
pg_userdatabase users
@@ -5869,6 +5874,53 @@
+
+ pg_timezonenames
+
+
+ pg_timezonenames
+
+
+
+ The view pg_timezonenames provides a list
+ of time zone abbreviations that are currently recognized by the datetime
+ input routines. The contents of this view change when the
+ run-time parameter is modified.
+
+
+
+ pg_timezonenames> Columns
+
+
+
+
+ Name
+ Type
+ Description
+
+
+
+
+ name
+ text
+ time zone abbreviation
+
+
+ utc_offset
+ interval
+ offset from UTC (positive means east of Greenwich)
+
+
+ is_dst
+ boolean
+ true if this is a daylight-savings zone
+
+
+
+
+
+
+
pg_user
diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index e073148ff9a..e967b235f36 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -1,4 +1,4 @@
-
+
Server Configuration
@@ -3410,19 +3410,20 @@ SELECT * FROM parent WHERE key = 2400;
-
- australian_timezones (boolean)
+
+ timezone_abbreviations (string)
- australian_timezones> configuration parameter
+ timezone_abbreviations> configuration parameter
- time zone>Australian>>
+ time zone names>>
- If set to on, ACST,
- CST, EST, and
- SAT are interpreted as Australian time
- zones rather than as North/South American time zones and
- Saturday. The default is off>.
+ Sets the collection of time zone abbreviations that will be accepted
+ by the server for datetime input. The default is 'Default',
+ which is a collection that works in most of the world; there are
+ also 'Australia' and 'India', and other collections can be defined
+ for a particular installation. See for more information.
diff --git a/doc/src/sgml/datetime.sgml b/doc/src/sgml/datetime.sgml
index 2bd42e5e52b..7e7e3278a0a 100644
--- a/doc/src/sgml/datetime.sgml
+++ b/doc/src/sgml/datetime.sgml
@@ -1,4 +1,4 @@
-
+
Date/Time Support
@@ -361,15 +361,25 @@
- and
- show the time zone
+ shows the time zone
abbreviations recognized by PostgreSQL
- in date/time input values. Note that these names are not>
- necessarily used for date/time output — output is driven by the
- official timezone abbreviation(s) associated with the currently selected
- parameter setting. (It is
- likely that future releases will make some use of timezone>
- for input as well.)
+ in date/time input values. These abbreviations are not
+ hard-wired into the server, but are obtained from a configuration
+ file (see ). Note that these
+ names are not> used for date/time output — all supported
+ output formats use numeric timezone displays to avoid ambiguity.
+
+
+
+ In addition to these abbreviations, the full timezone names shown in
+ can be used
+ in date/time input values. 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 timetz> values.
@@ -925,61 +935,6 @@
-
- Australian Time Zones
-
-
- There are three naming conflicts between Australian time zone
- names and time zone names commonly used in North and South America:
- ACST, CST, and
- EST. If the run-time option
- australian_timezones is set to true then
- ACST, CST,
- EST, and SAT are interpreted
- as Australian time zone names, as shown in . If it is false (which is the
- default), then ACST, CST,
- and EST are taken as American time zone names,
- and SAT is interpreted as a noise word
- indicating Saturday.
-
-
-
-
- Australian Time Zone Abbreviations for Input
-
-
-
- Time Zone
- Offset from UTC
- Description
-
-
-
-
- ACST
- +09:30
- Central Australia Standard Time
-
-
- CST
- +10:30
- Australian Central Standard Time
-
-
- EST
- +10:00
- Australian Eastern Standard Time
-
-
- SAT
- +09:30
- South Australian Standard Time
-
-
-
-
-
time zoneconfiguration names
@@ -988,13 +943,10 @@
shows the time zone
names recognized by PostgreSQL as valid
- settings for the parameter. Note that
- these names are conceptually as well as practically different from
- the names shown in :
- most of these names imply a local daylight-savings time rule, whereas
- the former names each represent just a fixed offset from UTC. That's why
- you always have to specify a date if you want to use these time zone
- names in timetz> values.
+ settings for the parameter. These names
+ are not hard-wired into the server, but are in fact names of configuration
+ files stored under .../share/timezone/> of the installation
+ directory.
@@ -1004,7 +956,7 @@
- Time Zone Names for date/time input values and for setting timezone>
+ Time Zone Names for setting timezone>
@@ -2230,7 +2182,8 @@
In addition to the names listed in the table,
- PostgreSQL will accept time zone names of the
+ PostgreSQL will accept
+ values of the
form STD>offset> or
STD>offset>DST>, where
STD> is a zone abbreviation, offset> is a
@@ -2250,6 +2203,108 @@
+
+ Date/Time Configuration Files
+
+
+ Since timezone abbreviations are not well standardized,
+ PostgreSQL provides a means to customize
+ the set of abbreviations accepted by the server. The
+ run-time parameter
+ determines the active set of abbreviations. While this parameter
+ can be altered by any database user, the possible values for it
+ are under the control of the database administrator — they
+ are in fact names of configuration files stored in
+ .../share/timezonesets/> of the installation directory.
+ By adding or altering files in that directory, the administrator
+ can set local policy for timezone abbreviations.
+
+
+
+ timezone_abbreviations> can be set to any file name
+ found in .../share/timezonesets/>, if the file's name
+ is entirely alphabetic. (The prohibition against non-alphabetic
+ characters in timezone_abbreviations> prevents reading
+ files outside the intended directory, as well as reading editor
+ backup files and other extraneous files.)
+
+
+
+ A timezone abbreviation file may contain blank lines and comments
+ beginning with #>. Non-comment lines must have one of
+ these formats:
+
+
+time_zone_nameoffset
+time_zone_nameoffset D
+@INCLUDE file_name
+@OVERRIDE
+
+
+
+
+ A time_zone_name is just the abbreviation
+ being defined. The offset is the zone's
+ offset in seconds from UTC, positive being east from Greenwich and
+ negative being west. For example, -18000 would be five hours west
+ of Greenwich, or North American east coast standard time. D>
+ indicates that the zone name represents local daylight-savings time
+ rather than standard time.
+
+
+
+ The @INCLUDE> syntax allows inclusion of another file in the
+ .../share/timezonesets/> directory. Inclusion can be nested,
+ to a limited depth.
+
+
+
+ The @OVERRIDE> syntax indicates that subsequent entries in the
+ file may override previous entries (i.e., entries obtained from included
+ files). Without this, conflicting definitions of the same timezone
+ abbreviation are considered an error.
+
+
+
+ In an unmodified installation, the file Default> contains
+ all the non-conflicting time zone abbreviations for most of the world.
+ Additional files Australia> and India> are
+ provided for those regions: these files first include the
+ Default> file and then add or modify timezones as needed.
+
+
+
+ For reference purposes, a standard installation also contains files
+ Africa.txt>, America.txt>, etc, containing
+ information about every time zone abbreviation known to be in use
+ according to the zic> timezone database. The zone name
+ definitions found in these files can be copied and pasted into a custom
+ configuration file as needed. Note that these files cannot be directly
+ referenced as timezone_abbreviations> settings, because of
+ the dot embedded in their names.
+
+
+
+
+ Time zone abbreviations defined in the configuration file override
+ non-timezone meanings built into PostgreSQL.
+ For example, the Australia> configuration file defines
+ SAT> (for South Australian Standard Time). When this
+ file is active, SAT> will not be recognized as an abbreviation
+ for Saturday.
+
+
+
+
+
+ If you modify files in .../share/timezonesets/>,
+ it is up to you to make backups — a normal database dump
+ will not include this directory.
+
+
+
+
+
History of Units
diff --git a/doc/src/sgml/ref/show.sgml b/doc/src/sgml/ref/show.sgml
index f6123ba5036..cf92bcec4e8 100644
--- a/doc/src/sgml/ref/show.sgml
+++ b/doc/src/sgml/ref/show.sgml
@@ -1,5 +1,5 @@
@@ -168,7 +168,6 @@ SHOW ALL;
--------------------------------+--------------------------------+----------------------------------------------------------------------------------------------
add_missing_from | off | Automatically adds missing table references to FROM clauses.
archive_command | unset | WAL archiving command.
- australian_timezones | off | Interprets ACST, CST, EST, and SAT as Australian time zones.
.
.
.
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index eba31082bc2..2190caa7c72 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -3,7 +3,7 @@
*
* Copyright (c) 1996-2006, PostgreSQL Global Development Group
*
- * $PostgreSQL: pgsql/src/backend/catalog/system_views.sql,v 1.27 2006/05/19 19:08:26 alvherre Exp $
+ * $PostgreSQL: pgsql/src/backend/catalog/system_views.sql,v 1.28 2006/07/25 03:51:21 tgl Exp $
*/
CREATE VIEW pg_roles AS
@@ -186,6 +186,11 @@ CREATE RULE pg_settings_n AS
GRANT SELECT, UPDATE ON pg_settings TO PUBLIC;
+CREATE VIEW pg_timezonenames AS
+ SELECT *
+ FROM pg_timezonenames() AS T
+ (name text, utc_offset interval, is_dst boolean);
+
-- Statistics views
CREATE VIEW pg_stat_all_tables AS
diff --git a/src/backend/utils/adt/datetime.c b/src/backend/utils/adt/datetime.c
index b5478ac3373..f4aceed0aa3 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.168 2006/07/14 05:28:28 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/datetime.c,v 1.169 2006/07/25 03:51:21 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -19,11 +19,15 @@
#include
#include
+#include "access/heapam.h"
#include "access/xact.h"
+#include "catalog/pg_type.h"
+#include "funcapi.h"
#include "miscadmin.h"
#include "utils/builtins.h"
#include "utils/datetime.h"
-#include "utils/guc.h"
+#include "utils/memutils.h"
+#include "utils/tzparser.h"
static int DecodeNumber(int flen, char *field, bool haveTextMonth,
@@ -37,7 +41,7 @@ static int DecodeTime(char *str, int fmask, int *tmask,
static int DecodeTimezone(char *str, int *tzp);
static int DecodePosixTimezone(char *str, int *tzp);
static int DecodeZicTimezone(char *str, int *tzp, struct pg_tm * tm);
-static datetkn *datebsearch(char *key, datetkn *base, unsigned int nel);
+static const datetkn *datebsearch(const char *key, const datetkn *base, int nel);
static int DecodeDate(char *str, int fmask, int *tmask, struct pg_tm * tm);
static void TrimTrailingZeros(char *str);
@@ -87,426 +91,92 @@ char *days[] = {"Sunday", "Monday", "Tuesday", "Wednesday",
* which are 30 or 45 minutes away from an even hour, most are on an hour
* boundary, and none on other boundaries.
*
- * Let's include all strings from my current zic time zone database.
- * Not all of them are unique, or even very understandable, so we will
- * leave some commented out for now.
+ * The static table contains no TZ or DTZ entries, rather those are loaded
+ * from configuration files and stored in timezonetktbl, which has the same
+ * format as the static datetktbl.
*/
-static datetkn datetktbl[] = {
+static datetkn *timezonetktbl = NULL;
+
+static int sztimezonetktbl = 0;
+
+static const datetkn datetktbl[] = {
/* text, token, lexval */
{EARLY, RESERV, DTK_EARLY}, /* "-infinity" reserved for "early time" */
{"abstime", IGNORE_DTF, 0}, /* for pre-v6.1 "Invalid Abstime" */
- {"acsst", DTZ, POS(42)}, /* Cent. Australia */
- {"acst", DTZ, NEG(16)}, /* Atlantic/Porto Acre Summer Time */
- {"act", TZ, NEG(20)}, /* Atlantic/Porto Acre Time */
{DA_D, ADBC, AD}, /* "ad" for years > 0 */
- {"adt", DTZ, NEG(12)}, /* Atlantic Daylight Time */
- {"aesst", DTZ, POS(44)}, /* E. Australia */
- {"aest", TZ, POS(40)}, /* Australia Eastern Std Time */
- {"aft", TZ, POS(18)}, /* Kabul */
- {"ahst", TZ, NEG(40)}, /* Alaska-Hawaii Std Time */
- {"akdt", DTZ, NEG(32)}, /* Alaska Daylight Time */
- {"akst", DTZ, NEG(36)}, /* Alaska Standard Time */
{"allballs", RESERV, DTK_ZULU}, /* 00:00:00 */
- {"almst", TZ, POS(28)}, /* Almaty Savings Time */
- {"almt", TZ, POS(24)}, /* Almaty Time */
{"am", AMPM, AM},
- {"amst", DTZ, POS(20)}, /* Armenia Summer Time (Yerevan) */
-#if 0
- {"amst", DTZ, NEG(12)}, /* Amazon Summer Time (Porto Velho) */
-#endif
- {"amt", TZ, POS(16)}, /* Armenia Time (Yerevan) */
-#if 0
- {"amt", TZ, NEG(16)}, /* Amazon Time (Porto Velho) */
-#endif
- {"anast", DTZ, POS(52)}, /* Anadyr Summer Time (Russia) */
- {"anat", TZ, POS(48)}, /* Anadyr Time (Russia) */
{"apr", MONTH, 4},
{"april", MONTH, 4},
-#if 0
- aqtst
- aqtt
- arst
-#endif
- {"art", TZ, NEG(12)}, /* Argentina Time */
-#if 0
- ashst
- ast /* Atlantic Standard Time, Arabia Standard
- * Time, Acre Standard Time */
-#endif
- {"ast", TZ, NEG(16)}, /* Atlantic Std Time (Canada) */
{"at", IGNORE_DTF, 0}, /* "at" (throwaway) */
{"aug", MONTH, 8},
{"august", MONTH, 8},
- {"awsst", DTZ, POS(36)}, /* W. Australia */
- {"awst", TZ, POS(32)}, /* W. Australia */
- {"awt", DTZ, NEG(12)},
- {"azost", DTZ, POS(0)}, /* Azores Summer Time */
- {"azot", TZ, NEG(4)}, /* Azores Time */
- {"azst", DTZ, POS(20)}, /* Azerbaijan Summer Time */
- {"azt", TZ, POS(16)}, /* Azerbaijan Time */
{DB_C, ADBC, BC}, /* "bc" for years <= 0 */
- {"bdst", TZ, POS(8)}, /* British Double Summer Time */
- {"bdt", TZ, POS(24)}, /* Dacca */
- {"bnt", TZ, POS(32)}, /* Brunei Darussalam Time */
- {"bort", TZ, POS(32)}, /* Borneo Time (Indonesia) */
-#if 0
- bortst
- bost
-#endif
- {"bot", TZ, NEG(16)}, /* Bolivia Time */
- {"bra", TZ, NEG(12)}, /* Brazil Time */
- {"brst", DTZ, NEG(8)}, /* Brasilia Summer Time */
- {"brt", TZ, NEG(12)}, /* Brasilia Time */
- {"bst", DTZ, POS(4)}, /* British Summer Time */
-#if 0
- {"bst", TZ, NEG(12)}, /* Brazil Standard Time */
- {"bst", DTZ, NEG(44)}, /* Bering Summer Time */
-#endif
- {"bt", TZ, POS(12)}, /* Baghdad Time */
- {"btt", TZ, POS(24)}, /* Bhutan Time */
- {"cadt", DTZ, POS(42)}, /* Central Australian DST */
- {"cast", TZ, POS(38)}, /* Central Australian ST */
- {"cat", TZ, NEG(40)}, /* Central Alaska Time */
- {"cct", TZ, POS(32)}, /* China Coast Time */
-#if 0
- {"cct", TZ, POS(26)}, /* Indian Cocos (Island) Time */
-#endif
- {"cdt", DTZ, NEG(20)}, /* Central Daylight Time */
- {"cest", DTZ, POS(8)}, /* Central European Dayl.Time */
- {"cet", TZ, POS(4)}, /* Central European Time */
- {"cetdst", DTZ, POS(8)}, /* Central European Dayl.Time */
- {"chadt", DTZ, POS(55)}, /* Chatham Island Daylight Time (13:45) */
- {"chast", TZ, POS(51)}, /* Chatham Island Time (12:45) */
-#if 0
- ckhst
-#endif
- {"ckt", TZ, POS(48)}, /* Cook Islands Time */
- {"clst", DTZ, NEG(12)}, /* Chile Summer Time */
- {"clt", TZ, NEG(16)}, /* Chile Time */
-#if 0
- cost
-#endif
- {"cot", TZ, NEG(20)}, /* Columbia Time */
- {"cst", TZ, NEG(24)}, /* Central Standard Time */
{DCURRENT, RESERV, DTK_CURRENT}, /* "current" is always now */
-#if 0
- cvst
-#endif
- {"cvt", TZ, POS(28)}, /* Christmas Island Time (Indian Ocean) */
- {"cxt", TZ, POS(28)}, /* Christmas Island Time (Indian Ocean) */
{"d", UNITS, DTK_DAY}, /* "day of month" for ISO input */
- {"davt", TZ, POS(28)}, /* Davis Time (Antarctica) */
- {"ddut", TZ, POS(40)}, /* Dumont-d'Urville Time (Antarctica) */
{"dec", MONTH, 12},
{"december", MONTH, 12},
- {"dnt", TZ, POS(4)}, /* Dansk Normal Tid */
{"dow", RESERV, DTK_DOW}, /* day of week */
{"doy", RESERV, DTK_DOY}, /* day of year */
{"dst", DTZMOD, 6},
-#if 0
- {"dusst", DTZ, POS(24)}, /* Dushanbe Summer Time */
-#endif
- {"easst", DTZ, NEG(20)}, /* Easter Island Summer Time */
- {"east", TZ, NEG(24)}, /* Easter Island Time */
- {"eat", TZ, POS(12)}, /* East Africa Time */
-#if 0
- {"east", DTZ, POS(16)}, /* Indian Antananarivo Savings Time */
- {"eat", TZ, POS(12)}, /* Indian Antananarivo Time */
- {"ect", TZ, NEG(16)}, /* Eastern Caribbean Time */
- {"ect", TZ, NEG(20)}, /* Ecuador Time */
-#endif
- {"edt", DTZ, NEG(16)}, /* Eastern Daylight Time */
- {"eest", DTZ, POS(12)}, /* Eastern Europe Summer Time */
- {"eet", TZ, POS(8)}, /* East. Europe, USSR Zone 1 */
- {"eetdst", DTZ, POS(12)}, /* Eastern Europe Daylight Time */
- {"egst", DTZ, POS(0)}, /* East Greenland Summer Time */
- {"egt", TZ, NEG(4)}, /* East Greenland Time */
-#if 0
- ehdt
-#endif
{EPOCH, RESERV, DTK_EPOCH}, /* "epoch" reserved for system epoch time */
- {"est", TZ, NEG(20)}, /* Eastern Standard Time */
{"feb", MONTH, 2},
{"february", MONTH, 2},
- {"fjst", DTZ, NEG(52)}, /* Fiji Summer Time (13 hour offset!) */
- {"fjt", TZ, NEG(48)}, /* Fiji Time */
- {"fkst", DTZ, NEG(12)}, /* Falkland Islands Summer Time */
- {"fkt", TZ, NEG(8)}, /* Falkland Islands Time */
- {"fnst", DTZ, NEG(4)}, /* Fernando de Noronha Summer Time */
- {"fnt", TZ, NEG(8)}, /* Fernando de Noronha Time */
{"fri", DOW, 5},
{"friday", DOW, 5},
- {"fst", TZ, POS(4)}, /* French Summer Time */
- {"fwt", DTZ, POS(8)}, /* French Winter Time */
- {"galt", TZ, NEG(24)}, /* Galapagos Time */
- {"gamt", TZ, NEG(36)}, /* Gambier Time */
- {"gest", DTZ, POS(20)}, /* Georgia Summer Time */
- {"get", TZ, POS(16)}, /* Georgia Time */
- {"gft", TZ, NEG(12)}, /* French Guiana Time */
-#if 0
- ghst
-#endif
- {"gilt", TZ, POS(48)}, /* Gilbert Islands Time */
- {"gmt", TZ, POS(0)}, /* Greenwich Mean Time */
- {"gst", TZ, POS(40)}, /* Guam Std Time, USSR Zone 9 */
- {"gyt", TZ, NEG(16)}, /* Guyana Time */
{"h", UNITS, DTK_HOUR}, /* "hour" */
-#if 0
- hadt
- hast
-#endif
- {"hdt", DTZ, NEG(36)}, /* Hawaii/Alaska Daylight Time */
-#if 0
- hkst
-#endif
- {"hkt", TZ, POS(32)}, /* Hong Kong Time */
-#if 0
- {"hmt", TZ, POS(12)}, /* Hellas ? ? */
- hovst
- hovt
-#endif
- {"hst", TZ, NEG(40)}, /* Hawaii Std Time */
-#if 0
- hwt
-#endif
- {"ict", TZ, POS(28)}, /* Indochina Time */
- {"idle", TZ, POS(48)}, /* Intl. Date Line, East */
- {"idlw", TZ, NEG(48)}, /* Intl. Date Line, West */
-#if 0
- idt /* Israeli, Iran, Indian Daylight Time */
-#endif
{LATE, RESERV, DTK_LATE}, /* "infinity" reserved for "late time" */
{INVALID, RESERV, DTK_INVALID}, /* "invalid" reserved for bad time */
- {"iot", TZ, POS(20)}, /* Indian Chagos Time */
- {"irkst", DTZ, POS(36)}, /* Irkutsk Summer Time */
- {"irkt", TZ, POS(32)}, /* Irkutsk Time */
- {"irt", TZ, POS(14)}, /* Iran Time */
-#if 0
- isst
-#endif
- {"ist", TZ, POS(8)}, /* Israel */
- {"it", TZ, POS(14)}, /* Iran Time */
{"j", UNITS, DTK_JULIAN},
{"jan", MONTH, 1},
{"january", MONTH, 1},
- {"javt", TZ, POS(28)}, /* Java Time (07:00? see JT) */
- {"jayt", TZ, POS(36)}, /* Jayapura Time (Indonesia) */
{"jd", UNITS, DTK_JULIAN},
- {"jst", TZ, POS(36)}, /* Japan Std Time,USSR Zone 8 */
- {"jt", TZ, POS(30)}, /* Java Time (07:30? see JAVT) */
{"jul", MONTH, 7},
{"julian", UNITS, DTK_JULIAN},
{"july", MONTH, 7},
{"jun", MONTH, 6},
{"june", MONTH, 6},
- {"kdt", DTZ, POS(40)}, /* Korea Daylight Time */
- {"kgst", DTZ, POS(24)}, /* Kyrgyzstan Summer Time */
- {"kgt", TZ, POS(20)}, /* Kyrgyzstan Time */
- {"kost", TZ, POS(48)}, /* Kosrae Time */
- {"krast", DTZ, POS(28)}, /* Krasnoyarsk Summer Time */
- {"krat", TZ, POS(32)}, /* Krasnoyarsk Standard Time */
- {"kst", TZ, POS(36)}, /* Korea Standard Time */
- {"lhdt", DTZ, POS(44)}, /* Lord Howe Daylight Time, Australia */
- {"lhst", TZ, POS(42)}, /* Lord Howe Standard Time, Australia */
- {"ligt", TZ, POS(40)}, /* From Melbourne, Australia */
- {"lint", TZ, POS(56)}, /* Line Islands Time (Kiribati; +14 hours!) */
- {"lkt", TZ, POS(24)}, /* Lanka Time */
{"m", UNITS, DTK_MONTH}, /* "month" for ISO input */
- {"magst", DTZ, POS(48)}, /* Magadan Summer Time */
- {"magt", TZ, POS(44)}, /* Magadan Time */
{"mar", MONTH, 3},
{"march", MONTH, 3},
- {"mart", TZ, NEG(38)}, /* Marquesas Time */
- {"mawt", TZ, POS(24)}, /* Mawson, Antarctica */
{"may", MONTH, 5},
- {"mdt", DTZ, NEG(24)}, /* Mountain Daylight Time */
- {"mest", DTZ, POS(8)}, /* Middle Europe Summer Time */
- {"met", TZ, POS(4)}, /* Middle Europe Time */
- {"metdst", DTZ, POS(8)}, /* Middle Europe Daylight Time */
- {"mewt", TZ, POS(4)}, /* Middle Europe Winter Time */
- {"mez", TZ, POS(4)}, /* Middle Europe Zone */
- {"mht", TZ, POS(48)}, /* Kwajalein */
{"mm", UNITS, DTK_MINUTE}, /* "minute" for ISO input */
- {"mmt", TZ, POS(26)}, /* Myanmar Time */
{"mon", DOW, 1},
{"monday", DOW, 1},
-#if 0
- most
-#endif
- {"mpt", TZ, POS(40)}, /* North Mariana Islands Time */
- {"msd", DTZ, POS(16)}, /* Moscow Summer Time */
- {"msk", TZ, POS(12)}, /* Moscow Time */
- {"mst", TZ, NEG(28)}, /* Mountain Standard Time */
- {"mt", TZ, POS(34)}, /* Moluccas Time */
- {"mut", TZ, POS(16)}, /* Mauritius Island Time */
- {"mvt", TZ, POS(20)}, /* Maldives Island Time */
- {"myt", TZ, POS(32)}, /* Malaysia Time */
-#if 0
- ncst
-#endif
- {"nct", TZ, POS(44)}, /* New Caledonia Time */
- {"ndt", DTZ, NEG(10)}, /* Nfld. Daylight Time */
- {"nft", TZ, NEG(14)}, /* Newfoundland Standard Time */
- {"nor", TZ, POS(4)}, /* Norway Standard Time */
{"nov", MONTH, 11},
{"november", MONTH, 11},
- {"novst", DTZ, POS(28)}, /* Novosibirsk Summer Time */
- {"novt", TZ, POS(24)}, /* Novosibirsk Standard Time */
{NOW, RESERV, DTK_NOW}, /* current transaction time */
- {"npt", TZ, POS(23)}, /* Nepal Standard Time (GMT-5:45) */
- {"nst", TZ, NEG(14)}, /* Nfld. Standard Time */
- {"nt", TZ, NEG(44)}, /* Nome Time */
- {"nut", TZ, NEG(44)}, /* Niue Time */
- {"nzdt", DTZ, POS(52)}, /* New Zealand Daylight Time */
- {"nzst", TZ, POS(48)}, /* New Zealand Standard Time */
- {"nzt", TZ, POS(48)}, /* New Zealand Time */
{"oct", MONTH, 10},
{"october", MONTH, 10},
- {"omsst", DTZ, POS(28)}, /* Omsk Summer Time */
- {"omst", TZ, POS(24)}, /* Omsk Time */
{"on", IGNORE_DTF, 0}, /* "on" (throwaway) */
- {"pdt", DTZ, NEG(28)}, /* Pacific Daylight Time */
-#if 0
- pest
-#endif
- {"pet", TZ, NEG(20)}, /* Peru Time */
- {"petst", DTZ, POS(52)}, /* Petropavlovsk-Kamchatski Summer Time */
- {"pett", TZ, POS(48)}, /* Petropavlovsk-Kamchatski Time */
- {"pgt", TZ, POS(40)}, /* Papua New Guinea Time */
- {"phot", TZ, POS(52)}, /* Phoenix Islands (Kiribati) Time */
-#if 0
- phst
-#endif
- {"pht", TZ, POS(32)}, /* Phillipine Time */
- {"pkt", TZ, POS(20)}, /* Pakistan Time */
{"pm", AMPM, PM},
- {"pmdt", DTZ, NEG(8)}, /* Pierre & Miquelon Daylight Time */
-#if 0
- pmst
-#endif
- {"pont", TZ, POS(44)}, /* Ponape Time (Micronesia) */
- {"pst", TZ, NEG(32)}, /* Pacific Standard Time */
- {"pwt", TZ, POS(36)}, /* Palau Time */
- {"pyst", DTZ, NEG(12)}, /* Paraguay Summer Time */
- {"pyt", TZ, NEG(16)}, /* Paraguay Time */
- {"ret", DTZ, POS(16)}, /* Reunion Island Time */
{"s", UNITS, DTK_SECOND}, /* "seconds" for ISO input */
- {"sadt", DTZ, POS(42)}, /* S. Australian Dayl. Time */
-#if 0
- samst
- samt
-#endif
- {"sast", TZ, POS(38)}, /* South Australian Std Time */
{"sat", DOW, 6},
{"saturday", DOW, 6},
-#if 0
- sbt
-#endif
- {"sct", DTZ, POS(16)}, /* Mahe Island Time */
{"sep", MONTH, 9},
{"sept", MONTH, 9},
{"september", MONTH, 9},
- {"set", TZ, NEG(4)}, /* Seychelles Time ?? */
-#if 0
- sgt
-#endif
- {"sst", DTZ, POS(8)}, /* Swedish Summer Time */
{"sun", DOW, 0},
{"sunday", DOW, 0},
- {"swt", TZ, POS(4)}, /* Swedish Winter Time */
-#if 0
- syot
-#endif
{"t", ISOTIME, DTK_TIME}, /* Filler for ISO time fields */
- {"tft", TZ, POS(20)}, /* Kerguelen Time */
- {"that", TZ, NEG(40)}, /* Tahiti Time */
{"thu", DOW, 4},
{"thur", DOW, 4},
{"thurs", DOW, 4},
{"thursday", DOW, 4},
- {"tjt", TZ, POS(20)}, /* Tajikistan Time */
- {"tkt", TZ, NEG(40)}, /* Tokelau Time */
- {"tmt", TZ, POS(20)}, /* Turkmenistan Time */
{TODAY, RESERV, DTK_TODAY}, /* midnight */
{TOMORROW, RESERV, DTK_TOMORROW}, /* tomorrow midnight */
-#if 0
- tost
-#endif
- {"tot", TZ, POS(52)}, /* Tonga Time */
-#if 0
- tpt
-#endif
- {"truk", TZ, POS(40)}, /* Truk Time */
{"tue", DOW, 2},
{"tues", DOW, 2},
{"tuesday", DOW, 2},
- {"tvt", TZ, POS(48)}, /* Tuvalu Time */
-#if 0
- uct
-#endif
- {"ulast", DTZ, POS(36)}, /* Ulan Bator Summer Time */
- {"ulat", TZ, POS(32)}, /* Ulan Bator Time */
{"undefined", RESERV, DTK_INVALID}, /* pre-v6.1 invalid time */
- {"ut", TZ, POS(0)},
- {"utc", TZ, POS(0)},
- {"uyst", DTZ, NEG(8)}, /* Uruguay Summer Time */
- {"uyt", TZ, NEG(12)}, /* Uruguay Time */
- {"uzst", DTZ, POS(24)}, /* Uzbekistan Summer Time */
- {"uzt", TZ, POS(20)}, /* Uzbekistan Time */
- {"vet", TZ, NEG(16)}, /* Venezuela Time */
- {"vlast", DTZ, POS(44)}, /* Vladivostok Summer Time */
- {"vlat", TZ, POS(40)}, /* Vladivostok Time */
-#if 0
- vust
-#endif
- {"vut", TZ, POS(44)}, /* Vanuata Time */
- {"wadt", DTZ, POS(32)}, /* West Australian DST */
- {"wakt", TZ, POS(48)}, /* Wake Time */
-#if 0
- warst
-#endif
- {"wast", TZ, POS(28)}, /* West Australian Std Time */
- {"wat", TZ, NEG(4)}, /* West Africa Time */
- {"wdt", DTZ, POS(36)}, /* West Australian DST */
{"wed", DOW, 3},
{"wednesday", DOW, 3},
{"weds", DOW, 3},
- {"west", DTZ, POS(4)}, /* Western Europe Summer Time */
- {"wet", TZ, POS(0)}, /* Western Europe */
- {"wetdst", DTZ, POS(4)}, /* Western Europe Daylight Savings Time */
- {"wft", TZ, POS(48)}, /* Wallis and Futuna Time */
- {"wgst", DTZ, NEG(8)}, /* West Greenland Summer Time */
- {"wgt", TZ, NEG(12)}, /* West Greenland Time */
- {"wst", TZ, POS(32)}, /* West Australian Standard Time */
{"y", UNITS, DTK_YEAR}, /* "year" for ISO input */
- {"yakst", DTZ, POS(40)}, /* Yakutsk Summer Time */
- {"yakt", TZ, POS(36)}, /* Yakutsk Time */
- {"yapt", TZ, POS(40)}, /* Yap Time (Micronesia) */
- {"ydt", DTZ, NEG(32)}, /* Yukon Daylight Time */
- {"yekst", DTZ, POS(24)}, /* Yekaterinburg Summer Time */
- {"yekt", TZ, POS(20)}, /* Yekaterinburg Time */
{YESTERDAY, RESERV, DTK_YESTERDAY}, /* yesterday midnight */
- {"yst", TZ, NEG(36)}, /* Yukon Standard Time */
- {"z", TZ, POS(0)}, /* time zone tag per ISO-8601 */
- {"zp4", TZ, NEG(16)}, /* UTC +4 hours. */
- {"zp5", TZ, NEG(20)}, /* UTC +5 hours. */
- {"zp6", TZ, NEG(24)}, /* UTC +6 hours. */
- {ZULU, TZ, POS(0)}, /* UTC */
};
-static unsigned int szdatetktbl = sizeof datetktbl / sizeof datetktbl[0];
-
-/* Used for SET australian_timezones to override North American ones */
-static datetkn australian_datetktbl[] = {
- {"acst", TZ, POS(38)}, /* Cent. Australia */
- {"cst", TZ, POS(42)}, /* Australia Central Std Time */
- {"east", TZ, POS(40)}, /* East Australian Std Time */
- {"est", TZ, POS(40)}, /* Australia Eastern Std Time */
- {"sat", TZ, POS(38)},
-};
-
-static unsigned int australian_szdatetktbl = sizeof australian_datetktbl /
-sizeof australian_datetktbl[0];
+static int szdatetktbl = sizeof datetktbl / sizeof datetktbl[0];
static datetkn deltatktbl[] = {
/* text, token, lexval */
@@ -576,11 +246,11 @@ static datetkn deltatktbl[] = {
{"yrs", UNITS, DTK_YEAR}, /* "years" relative */
};
-static unsigned int szdeltatktbl = sizeof deltatktbl / sizeof deltatktbl[0];
+static int szdeltatktbl = sizeof deltatktbl / sizeof deltatktbl[0];
-static datetkn *datecache[MAXDATEFIELDS] = {NULL};
+static const datetkn *datecache[MAXDATEFIELDS] = {NULL};
-static datetkn *deltacache[MAXDATEFIELDS] = {NULL};
+static const datetkn *deltacache[MAXDATEFIELDS] = {NULL};
/*
@@ -2998,21 +2668,15 @@ int
DecodeSpecial(int field, char *lowtoken, int *val)
{
int type;
- datetkn *tp;
+ const datetkn *tp;
- if (datecache[field] != NULL &&
- strncmp(lowtoken, datecache[field]->token, TOKMAXLEN) == 0)
- tp = datecache[field];
- else
+ tp = datecache[field];
+ if (tp == NULL || strncmp(lowtoken, tp->token, TOKMAXLEN) != 0)
{
- tp = NULL;
- if (Australian_timezones)
- tp = datebsearch(lowtoken, australian_datetktbl,
- australian_szdatetktbl);
- if (!tp)
+ tp = datebsearch(lowtoken, timezonetktbl, sztimezonetktbl);
+ if (tp == NULL)
tp = datebsearch(lowtoken, datetktbl, szdatetktbl);
}
- datecache[field] = tp;
if (tp == NULL)
{
type = UNKNOWN_FIELD;
@@ -3020,6 +2684,7 @@ DecodeSpecial(int field, char *lowtoken, int *val)
}
else
{
+ datecache[field] = tp;
type = tp->type;
switch (type)
{
@@ -3391,20 +3056,20 @@ DecodeInterval(char **field, int *ftype, int nf, int *dtype, struct pg_tm * tm,
/* DecodeUnits()
* Decode text string using lookup table.
- * This routine supports time interval decoding.
+ * This routine supports time interval decoding
+ * (hence, it need not recognize timezone names).
*/
int
DecodeUnits(int field, char *lowtoken, int *val)
{
int type;
- datetkn *tp;
+ const datetkn *tp;
- if (deltacache[field] != NULL &&
- strncmp(lowtoken, deltacache[field]->token, TOKMAXLEN) == 0)
- tp = deltacache[field];
- else
+ tp = deltacache[field];
+ if (tp == NULL || strncmp(lowtoken, tp->token, TOKMAXLEN) != 0)
+ {
tp = datebsearch(lowtoken, deltatktbl, szdeltatktbl);
- deltacache[field] = tp;
+ }
if (tp == NULL)
{
type = UNKNOWN_FIELD;
@@ -3412,6 +3077,7 @@ DecodeUnits(int field, char *lowtoken, int *val)
}
else
{
+ deltacache[field] = tp;
type = tp->type;
if (type == TZ || type == DTZ)
*val = FROMVAL(tp);
@@ -3477,10 +3143,10 @@ DateTimeParseError(int dterr, const char *str, const char *datatype)
* Binary search -- from Knuth (6.2.1) Algorithm B. Special case like this
* is WAY faster than the generic bsearch().
*/
-static datetkn *
-datebsearch(char *key, datetkn *base, unsigned int nel)
+static const datetkn *
+datebsearch(const char *key, const datetkn *base, int nel)
{
- datetkn *last = base + nel - 1,
+ const datetkn *last = base + nel - 1,
*position;
int result;
@@ -4082,30 +3748,15 @@ EncodeInterval(struct pg_tm * tm, fsec_t fsec, int style, char *str)
} /* EncodeInterval() */
-/* GUC assign_hook for australian_timezones */
-bool
-ClearDateCache(bool newval, bool doit, GucSource source)
-{
- int i;
-
- if (doit)
- {
- for (i = 0; i < MAXDATEFIELDS; i++)
- datecache[i] = NULL;
- }
-
- return true;
-}
-
/*
* We've been burnt by stupid errors in the ordering of the datetkn tables
* once too often. Arrange to check them during postmaster start.
*/
static bool
-CheckDateTokenTable(const char *tablename, datetkn *base, unsigned int nel)
+CheckDateTokenTable(const char *tablename, const datetkn *base, int nel)
{
bool ok = true;
- unsigned int i;
+ int i;
for (i = 1; i < nel; i++)
{
@@ -4131,8 +3782,135 @@ CheckDateTokenTables(void)
ok &= CheckDateTokenTable("datetktbl", datetktbl, szdatetktbl);
ok &= CheckDateTokenTable("deltatktbl", deltatktbl, szdeltatktbl);
- ok &= CheckDateTokenTable("australian_datetktbl",
- australian_datetktbl,
- australian_szdatetktbl);
return ok;
}
+
+/*
+ * This function gets called during timezone config file load or reload
+ * to create the final array of timezone tokens. The argument array
+ * is already sorted in name order. This data is in a temporary memory
+ * context and must be copied to somewhere permanent.
+ */
+void
+InstallTimeZoneAbbrevs(tzEntry *abbrevs, int n)
+{
+ datetkn *newtbl;
+ int i;
+
+ /*
+ * Copy the data into TopMemoryContext and convert to datetkn format.
+ */
+ newtbl = (datetkn *) MemoryContextAlloc(TopMemoryContext,
+ n * sizeof(datetkn));
+ for (i = 0; i < n; i++)
+ {
+ strncpy(newtbl[i].token, abbrevs[i].abbrev, TOKMAXLEN);
+ newtbl[i].type = abbrevs[i].is_dst ? DTZ : TZ;
+ TOVAL(&newtbl[i], abbrevs[i].offset / 60);
+ }
+
+ /* Check the ordering, if testing */
+ Assert(CheckDateTokenTable("timezone offset", newtbl, n));
+
+ /* Now safe to replace existing table (if any) */
+ if (timezonetktbl)
+ pfree(timezonetktbl);
+ timezonetktbl = newtbl;
+ sztimezonetktbl = n;
+
+ /* clear date cache in case it contains any stale timezone names */
+ for (i = 0; i < MAXDATEFIELDS; i++)
+ datecache[i] = NULL;
+}
+
+/*
+ * This set-returning function reads all the available time zone abbreviations
+ * and returns a set of (name, utc_offset, is_dst).
+ */
+Datum
+pg_timezonenames(PG_FUNCTION_ARGS)
+{
+ FuncCallContext *funcctx;
+ int *pindex;
+ Datum result;
+ Interval *resInterval;
+ HeapTuple tuple;
+ Datum values[3];
+ bool nulls[3];
+ char buffer[TOKMAXLEN + 1];
+ unsigned char *p;
+ struct pg_tm tm;
+
+ /* stuff done only on the first call of the function */
+ if (SRF_IS_FIRSTCALL())
+ {
+ TupleDesc tupdesc;
+ MemoryContext oldcontext;
+
+ /* create a function context for cross-call persistence */
+ funcctx = SRF_FIRSTCALL_INIT();
+
+ /*
+ * switch to memory context appropriate for multiple function
+ * calls
+ */
+ oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
+
+ /* allocate memory for user context */
+ pindex = (int *) palloc(sizeof(int));
+ *pindex = 0;
+ funcctx->user_fctx = (void *) pindex;
+
+ /*
+ * build tupdesc for result tuples. This must match the
+ * definition of the pg_timezonenames view in system_views.sql
+ */
+ tupdesc = CreateTemplateTupleDesc(3, false);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 1, "name",
+ TEXTOID, -1, 0);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 2, "utc_offset",
+ INTERVALOID, -1, 0);
+ TupleDescInitEntry(tupdesc, (AttrNumber) 3, "is_dst",
+ BOOLOID, -1, 0);
+
+ funcctx->tuple_desc = BlessTupleDesc(tupdesc);
+ MemoryContextSwitchTo(oldcontext);
+ }
+
+ /* stuff done on every call of the function */
+ funcctx = SRF_PERCALL_SETUP();
+ pindex = (int *) funcctx->user_fctx;
+
+ if (*pindex >= sztimezonetktbl)
+ SRF_RETURN_DONE(funcctx);
+
+ MemSet(nulls, 0, sizeof(nulls));
+
+ /*
+ * Convert name to text, using upcasing conversion that is the inverse
+ * of what ParseDateTime() uses.
+ */
+ strncpy(buffer, timezonetktbl[*pindex].token, TOKMAXLEN);
+ buffer[TOKMAXLEN] = '\0'; /* may not be null-terminated */
+ for (p = (unsigned char *) buffer; *p; p++)
+ *p = pg_toupper(*p);
+
+ values[0] = DirectFunctionCall1(textin, CStringGetDatum(buffer));
+
+ MemSet(&tm, 0, sizeof(struct pg_tm));
+ tm.tm_min = (-1) * FROMVAL(&timezonetktbl[*pindex]);
+ resInterval = (Interval *) palloc(sizeof(Interval));
+ tm2interval(&tm, 0, resInterval);
+ values[1] = IntervalPGetDatum(resInterval);
+
+ Assert(timezonetktbl[*pindex].type == DTZ ||
+ timezonetktbl[*pindex].type == TZ);
+ values[2] = BoolGetDatum(timezonetktbl[*pindex].type == DTZ);
+
+ (*pindex)++;
+
+ tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls);
+ result = HeapTupleGetDatum(tuple);
+
+ SRF_RETURN_NEXT(funcctx, result);
+}
diff --git a/src/backend/utils/misc/Makefile b/src/backend/utils/misc/Makefile
index 5a37d7790b3..41d2571978d 100644
--- a/src/backend/utils/misc/Makefile
+++ b/src/backend/utils/misc/Makefile
@@ -4,7 +4,7 @@
# Makefile for utils/misc
#
# IDENTIFICATION
-# $PostgreSQL: pgsql/src/backend/utils/misc/Makefile,v 1.25 2006/03/07 01:03:12 tgl Exp $
+# $PostgreSQL: pgsql/src/backend/utils/misc/Makefile,v 1.26 2006/07/25 03:51:21 tgl Exp $
#
#-------------------------------------------------------------------------
@@ -14,7 +14,7 @@ include $(top_builddir)/src/Makefile.global
override CPPFLAGS := -I$(srcdir) $(CPPFLAGS)
-OBJS = guc.o help_config.o pg_rusage.o ps_status.o superuser.o
+OBJS = guc.o help_config.o pg_rusage.o ps_status.o superuser.o tzparser.o
# This location might depend on the installation directories. Therefore
# we can't subsitute it into pg_config.h.
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index f1bc6e11c48..400a267e704 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -10,7 +10,7 @@
* Written by Peter Eisentraut .
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.328 2006/07/14 14:52:25 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.329 2006/07/25 03:51:21 tgl Exp $
*
*--------------------------------------------------------------------
*/
@@ -26,6 +26,7 @@
#endif
+#include "access/gin.h"
#include "access/twophase.h"
#include "access/xact.h"
#include "catalog/namespace.h"
@@ -57,7 +58,7 @@
#include "utils/memutils.h"
#include "utils/pg_locale.h"
#include "utils/ps_status.h"
-#include "access/gin.h"
+#include "utils/tzparser.h"
#ifndef PG_KRB_SRVTAB
#define PG_KRB_SRVTAB ""
@@ -131,6 +132,7 @@ static bool assign_log_stats(bool newval, bool doit, GucSource source);
static bool assign_transaction_read_only(bool newval, bool doit, GucSource source);
static const char *assign_canonical_path(const char *newval, bool doit, GucSource source);
static const char *assign_backslash_quote(const char *newval, bool doit, GucSource source);
+static const char *assign_timezone_abbreviations(const char *newval, bool doit, GucSource source);
static bool assign_tcp_keepalives_idle(int newval, bool doit, GucSource source);
static bool assign_tcp_keepalives_interval(int newval, bool doit, GucSource source);
@@ -163,8 +165,6 @@ bool log_btree_build_stats = false;
bool SQL_inheritance = true;
-bool Australian_timezones = false;
-
bool Password_encryption = true;
bool default_with_oids = false;
@@ -216,6 +216,7 @@ static char *timezone_string;
static char *XactIsoLevel_string;
static char *data_directory;
static char *custom_variable_classes;
+static char *timezone_abbreviations;
static int max_function_args;
static int max_index_keys;
static int max_identifier_length;
@@ -806,15 +807,6 @@ static struct config_bool ConfigureNamesBool[] =
&SQL_inheritance,
true, NULL, NULL
},
- {
- {"australian_timezones", PGC_USERSET, CLIENT_CONN_LOCALE,
- gettext_noop("Interprets ACST, CST, EST, and SAT as Australian time zones."),
- gettext_noop("Otherwise they are interpreted as North/South American "
- "time zones and Saturday.")
- },
- &Australian_timezones,
- false, ClearDateCache, NULL
- },
{
{"password_encryption", PGC_USERSET, CONN_AUTH_SECURITY,
gettext_noop("Encrypt passwords."),
@@ -2077,6 +2069,14 @@ static struct config_string ConfigureNamesString[] =
&timezone_string,
"UNKNOWN", assign_timezone, show_timezone
},
+ {
+ {"timezone_abbreviations", PGC_USERSET, CLIENT_CONN_LOCALE,
+ gettext_noop("Selects a file of timezone abbreviations"),
+ NULL,
+ },
+ &timezone_abbreviations,
+ "Default", assign_timezone_abbreviations, NULL
+ },
{
{"transaction_isolation", PGC_USERSET, CLIENT_CONN_STATEMENT,
@@ -6101,6 +6101,30 @@ assign_backslash_quote(const char *newval, bool doit, GucSource source)
return newval;
}
+static const char *
+assign_timezone_abbreviations(const char *newval, bool doit, GucSource source)
+{
+ /* Loading abbrev file is expensive, so only do it when value changes */
+ if (timezone_abbreviations == NULL ||
+ strcmp(timezone_abbreviations, newval) != 0)
+ {
+ int elevel;
+
+ /*
+ * If reading config file, only the postmaster should bleat loudly
+ * about problems. Otherwise, it's just this one process doing it,
+ * and we use WARNING message level.
+ */
+ if (source == PGC_S_FILE)
+ elevel = IsUnderPostmaster ? DEBUG2 : LOG;
+ else
+ elevel = WARNING;
+ if (!load_tzoffsets(newval, doit, elevel))
+ return NULL;
+ }
+ return newval;
+}
+
static bool
assign_tcp_keepalives_idle(int newval, bool doit, GucSource source)
{
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index e394915ae5a..00a34579f9b 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -397,7 +397,13 @@
#datestyle = 'iso, mdy'
#timezone = unknown # actually, defaults to TZ
# environment setting
-#australian_timezones = off
+#timezone_abbreviations = 'Default' # select the set of available timezone
+ # abbreviations. Currently, there are
+ # Default
+ # Australia
+ # India
+ # However you can also create your own
+ # file in share/timezonesets/.
#extra_float_digits = 0 # min -15, max 2
#client_encoding = sql_ascii # actually, defaults to database
# encoding
diff --git a/src/backend/utils/misc/tzparser.c b/src/backend/utils/misc/tzparser.c
new file mode 100644
index 00000000000..1a092ca2422
--- /dev/null
+++ b/src/backend/utils/misc/tzparser.c
@@ -0,0 +1,461 @@
+/*-------------------------------------------------------------------------
+ *
+ * tzparser.c
+ * Functions for parsing timezone offset files
+ *
+ * Note: we generally should not throw any errors in this file, but instead
+ * try to return an error code. This is not completely bulletproof at
+ * present --- in particular out-of-memory will throw an error. Could
+ * probably fix with PG_TRY if necessary.
+ *
+ *
+ * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * $PostgreSQL: pgsql/src/backend/utils/misc/tzparser.c,v 1.1 2006/07/25 03:51:21 tgl Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres.h"
+
+#include
+
+#include "miscadmin.h"
+#include "storage/fd.h"
+#include "utils/datetime.h"
+#include "utils/memutils.h"
+#include "utils/tzparser.h"
+
+
+#define WHITESPACE " \t\n\r"
+
+static int tz_elevel; /* to avoid passing this around a lot */
+
+static bool validateTzEntry(tzEntry *tzentry);
+static bool splitTzLine(const char *filename, int lineno,
+ char *line, tzEntry *tzentry);
+static int addToArray(tzEntry **base, int *arraysize, int n,
+ tzEntry *entry, bool override);
+static int ParseTzFile(const char *filename, int depth,
+ tzEntry **base, int *arraysize, int n);
+
+
+/*
+ * Apply additional validation checks to a tzEntry
+ *
+ * Returns TRUE if OK, else false
+ */
+static bool
+validateTzEntry(tzEntry *tzentry)
+{
+ unsigned char *p;
+
+ /*
+ * Check restrictions imposed by datetkntbl storage format (see datetime.c)
+ */
+ if (strlen(tzentry->abbrev) > TOKMAXLEN)
+ {
+ ereport(tz_elevel,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("time zone abbreviation \"%s\" is too long (maximum %d characters) in time zone file \"%s\", line %d",
+ tzentry->abbrev, TOKMAXLEN,
+ tzentry->filename, tzentry->lineno)));
+ return false;
+ }
+ if (tzentry->offset % 900 != 0)
+ {
+ ereport(tz_elevel,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("time zone offset %d is not a multiple of 900 sec (15 min) in time zone file \"%s\", line %d",
+ tzentry->offset,
+ tzentry->filename, tzentry->lineno)));
+ return false;
+ }
+
+ /*
+ * Sanity-check the offset: shouldn't exceed 14 hours
+ */
+ if (tzentry->offset > 14*60*60 ||
+ tzentry->offset < -14*60*60)
+ {
+ ereport(tz_elevel,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("time zone offset %d is out of range in time zone file \"%s\", line %d",
+ tzentry->offset,
+ tzentry->filename, tzentry->lineno)));
+ return false;
+ }
+
+ /*
+ * Convert abbrev to lowercase (must match datetime.c's conversion)
+ */
+ for (p = (unsigned char *) tzentry->abbrev; *p; p++)
+ *p = pg_tolower(*p);
+
+ return true;
+}
+
+/*
+ * Attempt to parse the line as a timezone abbrev spec (name, offset, dst)
+ *
+ * Returns TRUE if OK, else false; data is stored in *tzentry
+ */
+static bool
+splitTzLine(const char *filename, int lineno, char *line, tzEntry *tzentry)
+{
+ char *abbrev;
+ char *offset;
+ char *offset_endptr;
+ char *remain;
+ char *is_dst;
+
+ tzentry->lineno = lineno;
+ tzentry->filename = filename;
+
+ abbrev = strtok(line, WHITESPACE);
+ if (!abbrev)
+ {
+ ereport(tz_elevel,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("missing time zone abbreviation in time zone file \"%s\", line %d",
+ filename, lineno)));
+ return false;
+ }
+ tzentry->abbrev = abbrev;
+
+ offset = strtok(NULL, WHITESPACE);
+ if (!offset)
+ {
+ ereport(tz_elevel,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("missing time zone offset in time zone file \"%s\", line %d",
+ filename, lineno)));
+ return false;
+ }
+ tzentry->offset = strtol(offset, &offset_endptr, 10);
+ if (offset_endptr == offset || *offset_endptr != '\0')
+ {
+ ereport(tz_elevel,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("invalid number for time zone offset in time zone file \"%s\", line %d",
+ filename, lineno)));
+ return false;
+ }
+
+ is_dst = strtok(NULL, WHITESPACE);
+ if (is_dst && pg_strcasecmp(is_dst, "D") == 0)
+ {
+ tzentry->is_dst = true;
+ remain = strtok(NULL, WHITESPACE);
+ }
+ else
+ {
+ /* there was no 'D' dst specifier */
+ tzentry->is_dst = false;
+ remain = is_dst;
+ }
+
+ if (!remain) /* no more non-whitespace chars */
+ return true;
+
+ if (remain[0] != '#') /* must be a comment */
+ {
+ ereport(tz_elevel,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("invalid syntax in time zone file \"%s\", line %d",
+ filename, lineno)));
+ return false;
+ }
+ return true;
+}
+
+/*
+ * Insert entry into sorted array
+ *
+ * *base: base address of array (changeable if must enlarge array)
+ * *arraysize: allocated length of array (changeable if must enlarge array)
+ * n: current number of valid elements in array
+ * entry: new data to insert
+ * override: TRUE if OK to override
+ *
+ * Returns the new array length (new value for n), or -1 if error
+ */
+static int
+addToArray(tzEntry **base, int *arraysize, int n,
+ tzEntry *entry, bool override)
+{
+ tzEntry* arrayptr;
+ int low;
+ int high;
+
+ /*
+ * Search the array for a duplicate; as a useful side effect, the array
+ * is maintained in sorted order. We use strcmp() to ensure we match
+ * the sort order datetime.c expects.
+ */
+ arrayptr = *base;
+ low = 0;
+ high = n-1;
+ while (low <= high)
+ {
+ int mid = (low + high) >> 1;
+ tzEntry *midptr = arrayptr + mid;
+ int cmp;
+
+ cmp = strcmp(entry->abbrev, midptr->abbrev);
+ if (cmp < 0)
+ high = mid - 1;
+ else if (cmp > 0)
+ low = mid + 1;
+ else
+ {
+ /*
+ * Found a duplicate entry; complain unless it's the same.
+ */
+ if (midptr->offset == entry->offset &&
+ midptr->is_dst == entry->is_dst)
+ {
+ /* return unchanged array */
+ return n;
+ }
+ if (override)
+ {
+ /* same abbrev but something is different, override */
+ midptr->offset = entry->offset;
+ midptr->is_dst = entry->is_dst;
+ return n;
+ }
+ /* same abbrev but something is different, complain */
+ ereport(tz_elevel,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("time zone abbreviation \"%s\" is multiply defined",
+ entry->abbrev),
+ errdetail("Time zone file \"%s\", line %d conflicts with file \"%s\", line %d.",
+ midptr->filename, midptr->lineno,
+ entry->filename, entry->lineno)));
+ return -1;
+ }
+ }
+
+ /*
+ * No match, insert at position "low".
+ */
+ if (n >= *arraysize)
+ {
+ *arraysize *= 2;
+ *base = (tzEntry *) repalloc(*base, *arraysize * sizeof(tzEntry));
+ }
+
+ arrayptr = *base + low;
+
+ memmove(arrayptr + 1, arrayptr, (n - low) * sizeof(tzEntry));
+
+ memcpy(arrayptr, entry, sizeof(tzEntry));
+
+ /* Must dup the abbrev to ensure it survives */
+ arrayptr->abbrev = pstrdup(entry->abbrev);
+
+ return n+1;
+}
+
+/*
+ * Parse a single timezone abbrev file --- can recurse to handle @INCLUDE
+ *
+ * filename: user-specified file name (does not include path)
+ * depth: current recursion depth
+ * *base: array for results (changeable if must enlarge array)
+ * *arraysize: allocated length of array (changeable if must enlarge array)
+ * n: current number of valid elements in array
+ *
+ * Returns the new array length (new value for n), or -1 if error
+ */
+static int
+ParseTzFile(const char *filename, int depth,
+ tzEntry **base, int *arraysize, int n)
+{
+ char share_path[MAXPGPATH];
+ char file_path[MAXPGPATH];
+ FILE *tzFile;
+ char tzbuf[1024];
+ char *line;
+ tzEntry tzentry;
+ int lineno = 0;
+ bool override = false;
+ const char *p;
+
+ /*
+ * We enforce that the filename is all alpha characters. This may be
+ * overly restrictive, but we don't want to allow access to anything
+ * outside the timezonesets directory, so for instance '/' *must* be
+ * rejected.
+ */
+ for (p = filename; *p; p++)
+ {
+ if (!isalpha((unsigned char) *p))
+ {
+ /* at level 0, we need no ereport since guc.c will say enough */
+ if (depth > 0)
+ ereport(tz_elevel,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("invalid time zone file name \"%s\"",
+ filename)));
+ return -1;
+ }
+ }
+
+ /*
+ * The maximal recursion depth is a pretty arbitrary setting.
+ * It is hard to imagine that someone needs more than 3 levels so stick
+ * with this conservative setting until someone complains.
+ */
+ if (depth > 3)
+ {
+ ereport(tz_elevel,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("time zone file recursion limit exceeded in file \"%s\"",
+ filename)));
+ return -1;
+ }
+
+ get_share_path(my_exec_path, share_path);
+ snprintf(file_path, sizeof(file_path), "%s/timezonesets/%s",
+ share_path, filename);
+ tzFile = AllocateFile(file_path, "r");
+ if (!tzFile)
+ {
+ /* at level 0, if file doesn't exist, guc.c's complaint is enough */
+ if (errno != ENOENT || depth > 0)
+ ereport(tz_elevel,
+ (errcode_for_file_access(),
+ errmsg("could not read time zone file \"%s\": %m",
+ filename)));
+ return -1;
+ }
+
+ while (!feof(tzFile))
+ {
+ lineno++;
+ if (fgets(tzbuf, sizeof(tzbuf), tzFile) == NULL)
+ {
+ if (ferror(tzFile))
+ {
+ ereport(tz_elevel,
+ (errcode_for_file_access(),
+ errmsg("could not read time zone file \"%s\": %m",
+ filename)));
+ return -1;
+ }
+ /* else we're at EOF after all */
+ break;
+ }
+ if (strlen(tzbuf) == sizeof(tzbuf)-1)
+ {
+ /* the line is too long for tzbuf */
+ ereport(tz_elevel,
+ (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
+ errmsg("line is too long in time zone file \"%s\", line %d",
+ filename, lineno)));
+ return -1;
+ }
+
+ /* skip over whitespace */
+ line = tzbuf;
+ while (*line && isspace((unsigned char) *line))
+ line++;
+
+ if (*line == '\0') /* empty line */
+ continue;
+ if (*line == '#') /* comment line */
+ continue;
+
+ if (pg_strncasecmp(line, "@INCLUDE", strlen("@INCLUDE")) == 0)
+ {
+ /* pstrdup so we can use filename in result data structure */
+ char* includeFile = pstrdup(line + strlen("@INCLUDE"));
+
+ includeFile = strtok(includeFile, WHITESPACE);
+ if (!includeFile || !*includeFile)
+ {
+ ereport(tz_elevel,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("@INCLUDE without filename in time zone file \"%s\", line %d",
+ filename, lineno)));
+ return -1;
+ }
+ n = ParseTzFile(includeFile, depth + 1,
+ base, arraysize, n);
+ if (n < 0)
+ return -1;
+ continue;
+ }
+
+ if (pg_strncasecmp(line, "@OVERRIDE", strlen("@OVERRIDE")) == 0)
+ {
+ override = true;
+ continue;
+ }
+
+ if (!splitTzLine(filename, lineno, line, &tzentry))
+ return -1;
+ if (!validateTzEntry(&tzentry))
+ return -1;
+ n = addToArray(base, arraysize, n, &tzentry, override);
+ if (n < 0)
+ return -1;
+ }
+
+ FreeFile(tzFile);
+
+ return n;
+}
+
+/*
+ * load_tzoffsets --- read and parse the specified timezone offset file
+ *
+ * filename: name specified by user
+ * doit: whether to actually apply the new values, or just check
+ * elevel: elog reporting level (will be less than ERROR)
+ *
+ * Returns TRUE if OK, FALSE if not; should avoid erroring out
+ */
+bool
+load_tzoffsets(const char *filename, bool doit, int elevel)
+{
+ MemoryContext tmpContext;
+ MemoryContext oldContext;
+ tzEntry *array;
+ int arraysize;
+ int n;
+
+ tz_elevel = elevel;
+
+ /*
+ * Create a temp memory context to work in. This makes it easy to
+ * clean up afterwards.
+ */
+ tmpContext = AllocSetContextCreate(CurrentMemoryContext,
+ "TZParserMemory",
+ ALLOCSET_SMALL_MINSIZE,
+ ALLOCSET_SMALL_INITSIZE,
+ ALLOCSET_SMALL_MAXSIZE);
+ oldContext = MemoryContextSwitchTo(tmpContext);
+
+ /* Initialize array at a reasonable size */
+ arraysize = 128;
+ array = (tzEntry *) palloc(arraysize * sizeof(tzEntry));
+
+ /* Parse the file(s) */
+ n = ParseTzFile(filename, 0, &array, &arraysize, 0);
+
+ /* If no errors and we should apply the result, pass it to datetime.c */
+ if (n >= 0 && doit)
+ InstallTimeZoneAbbrevs(array, n);
+
+ /* Clean up */
+ MemoryContextSwitchTo(oldContext);
+ MemoryContextDelete(tmpContext);
+
+ return (n >= 0);
+}
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
index ce03edd0b16..93ce0809e00 100644
--- a/src/include/catalog/catversion.h
+++ b/src/include/catalog/catversion.h
@@ -37,7 +37,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.339 2006/07/21 20:51:33 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.340 2006/07/25 03:51:21 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -53,6 +53,6 @@
*/
/* yyyymmddN */
-#define CATALOG_VERSION_NO 200607211
+#define CATALOG_VERSION_NO 200607241
#endif
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index 9743d6c4a8f..7f68894d8d3 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.416 2006/07/21 20:51:33 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.417 2006/07/25 03:51:21 tgl Exp $
*
* NOTES
* The script catalog/genbki.sh reads this file and generates .bki
@@ -3731,6 +3731,8 @@ DATA(insert OID = 2510 ( pg_prepared_statement PGNSP PGUID 12 f f t t s 0 2249
DESCR("get the prepared statements for this session");
DATA(insert OID = 2511 ( pg_cursor PGNSP PGUID 12 f f t t s 0 2249 "" _null_ _null_ _null_ pg_cursor - _null_ ));
DESCR("get the open cursors for this session");
+DATA(insert OID = 2599 ( pg_timezonenames PGNSP PGUID 12 f f t t s 0 2249 "" _null_ _null_ _null_ pg_timezonenames - _null_ ));
+DESCR("get the available time zone names");
/* non-persistent series generator */
DATA(insert OID = 1066 ( generate_series PGNSP PGUID 12 f f t t v 3 23 "23 23 23" _null_ _null_ _null_ generate_series_step_int4 - _null_ ));
diff --git a/src/include/utils/datetime.h b/src/include/utils/datetime.h
index 838684695fe..17ae2621355 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.59 2006/06/06 16:20:11 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/utils/datetime.h,v 1.60 2006/07/25 03:51:22 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -20,6 +20,7 @@
#include
#include "utils/timestamp.h"
+#include "utils/tzparser.h"
/* ----------------------------------------------------------------
@@ -300,5 +301,8 @@ extern int DecodeUnits(int field, char *lowtoken, int *val);
extern int j2day(int jd);
extern bool CheckDateTokenTables(void);
+extern void InstallTimeZoneAbbrevs(tzEntry *abbrevs, int n);
+
+extern Datum pg_timezonenames(PG_FUNCTION_ARGS);
#endif /* DATETIME_H */
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 2024a05d182..f8938d9433a 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -7,7 +7,7 @@
* Copyright (c) 2000-2006, PostgreSQL Global Development Group
* Written by Peter Eisentraut .
*
- * $PostgreSQL: pgsql/src/include/utils/guc.h,v 1.69 2006/07/13 18:01:02 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/utils/guc.h,v 1.70 2006/07/25 03:51:22 tgl Exp $
*--------------------------------------------------------------------
*/
#ifndef GUC_H
@@ -116,7 +116,6 @@ extern bool log_statement_stats;
extern bool log_btree_build_stats;
extern bool SQL_inheritance;
-extern bool Australian_timezones;
extern bool default_with_oids;
@@ -220,9 +219,6 @@ extern void read_nondefault_variables(void);
* belong in.
*/
-/* in utils/adt/datetime.c */
-extern bool ClearDateCache(bool newval, bool doit, GucSource source);
-
/* in commands/tablespace.c */
extern const char *assign_default_tablespace(const char *newval,
bool doit, GucSource source);
diff --git a/src/include/utils/tzparser.h b/src/include/utils/tzparser.h
new file mode 100644
index 00000000000..4b7226eb444
--- /dev/null
+++ b/src/include/utils/tzparser.h
@@ -0,0 +1,35 @@
+/*-------------------------------------------------------------------------
+ *
+ * tzparser.h
+ * Timezone offset file parsing definitions.
+ *
+ * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * $PostgreSQL: pgsql/src/include/utils/tzparser.h,v 1.1 2006/07/25 03:51:22 tgl Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef TZPARSER_H
+#define TZPARSER_H
+
+/*
+ * The result of parsing a timezone configuration file is an array of
+ * these structs, in order by abbrev. We export this because datetime.c
+ * needs it.
+ */
+typedef struct tzEntry
+{
+ /* the actual data: TZ abbrev (downcased), offset, DST flag */
+ char *abbrev;
+ int offset; /* in seconds from UTC */
+ bool is_dst;
+ /* source information (for error messages) */
+ int lineno;
+ const char *filename;
+} tzEntry;
+
+
+extern bool load_tzoffsets(const char *filename, bool doit, int elevel);
+
+#endif /* TZPARSER_H */
diff --git a/src/test/regress/expected/horology.out b/src/test/regress/expected/horology.out
index 8ca242cbf44..15b397c74f2 100644
--- a/src/test/regress/expected/horology.out
+++ b/src/test/regress/expected/horology.out
@@ -1,8 +1,6 @@
--
-- HOROLOGY
--
--- needed so tests pass even in Australia
-SET australian_timezones = 'off';
SET DateStyle = 'Postgres, MDY';
--
-- Test various input formats
diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out
index 76a1a54e5dd..350d73a7353 100644
--- a/src/test/regress/expected/rules.out
+++ b/src/test/regress/expected/rules.out
@@ -1306,6 +1306,7 @@ SELECT viewname, definition FROM pg_views WHERE schemaname <> 'information_schem
pg_statio_user_tables | SELECT pg_statio_all_tables.relid, pg_statio_all_tables.schemaname, pg_statio_all_tables.relname, pg_statio_all_tables.heap_blks_read, pg_statio_all_tables.heap_blks_hit, pg_statio_all_tables.idx_blks_read, pg_statio_all_tables.idx_blks_hit, pg_statio_all_tables.toast_blks_read, pg_statio_all_tables.toast_blks_hit, pg_statio_all_tables.tidx_blks_read, pg_statio_all_tables.tidx_blks_hit FROM pg_statio_all_tables WHERE (pg_statio_all_tables.schemaname <> ALL (ARRAY['pg_catalog'::name, 'pg_toast'::name, 'information_schema'::name]));
pg_stats | SELECT n.nspname AS schemaname, c.relname AS tablename, a.attname, s.stanullfrac AS null_frac, s.stawidth AS avg_width, s.stadistinct AS n_distinct, CASE 1 WHEN s.stakind1 THEN s.stavalues1 WHEN s.stakind2 THEN s.stavalues2 WHEN s.stakind3 THEN s.stavalues3 WHEN s.stakind4 THEN s.stavalues4 ELSE NULL::"unknown" END AS most_common_vals, CASE 1 WHEN s.stakind1 THEN s.stanumbers1 WHEN s.stakind2 THEN s.stanumbers2 WHEN s.stakind3 THEN s.stanumbers3 WHEN s.stakind4 THEN s.stanumbers4 ELSE NULL::real[] END AS most_common_freqs, CASE 2 WHEN s.stakind1 THEN s.stavalues1 WHEN s.stakind2 THEN s.stavalues2 WHEN s.stakind3 THEN s.stavalues3 WHEN s.stakind4 THEN s.stavalues4 ELSE NULL::"unknown" END AS histogram_bounds, CASE 3 WHEN s.stakind1 THEN s.stanumbers1[1] WHEN s.stakind2 THEN s.stanumbers2[1] WHEN s.stakind3 THEN s.stanumbers3[1] WHEN s.stakind4 THEN s.stanumbers4[1] ELSE NULL::real END AS correlation FROM (((pg_statistic s JOIN pg_class c ON ((c.oid = s.starelid))) JOIN pg_attribute a ON (((c.oid = a.attrelid) AND (a.attnum = s.staattnum)))) LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) WHERE has_table_privilege(c.oid, 'select'::text);
pg_tables | SELECT n.nspname AS schemaname, c.relname AS tablename, pg_get_userbyid(c.relowner) AS tableowner, t.spcname AS "tablespace", c.relhasindex AS hasindexes, c.relhasrules AS hasrules, (c.reltriggers > 0) AS hastriggers FROM ((pg_class c LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) LEFT JOIN pg_tablespace t ON ((t.oid = c.reltablespace))) WHERE (c.relkind = 'r'::"char");
+ pg_timezonenames | SELECT t.name, t.utc_offset, t.is_dst FROM pg_timezonenames() t(name text, utc_offset interval, is_dst boolean);
pg_user | SELECT pg_shadow.usename, pg_shadow.usesysid, pg_shadow.usecreatedb, pg_shadow.usesuper, pg_shadow.usecatupd, '********'::text AS passwd, pg_shadow.valuntil, pg_shadow.useconfig FROM pg_shadow;
pg_views | SELECT n.nspname AS schemaname, c.relname AS viewname, pg_get_userbyid(c.relowner) AS viewowner, pg_get_viewdef(c.oid) AS definition FROM (pg_class c LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) WHERE (c.relkind = 'v'::"char");
rtest_v1 | SELECT rtest_t1.a, rtest_t1.b FROM rtest_t1;
@@ -1322,7 +1323,7 @@ SELECT viewname, definition FROM pg_views WHERE schemaname <> 'information_schem
shoelace_obsolete | SELECT shoelace.sl_name, shoelace.sl_avail, shoelace.sl_color, shoelace.sl_len, shoelace.sl_unit, shoelace.sl_len_cm FROM shoelace WHERE (NOT (EXISTS (SELECT shoe.shoename FROM shoe WHERE (shoe.slcolor = shoelace.sl_color))));
street | SELECT r.name, r.thepath, c.cname FROM ONLY road r, real_city c WHERE (c.outline ## r.thepath);
toyemp | SELECT emp.name, emp.age, emp."location", (12 * emp.salary) AS annualsal FROM emp;
-(46 rows)
+(47 rows)
SELECT tablename, rulename, definition FROM pg_rules
ORDER BY tablename, rulename;
diff --git a/src/test/regress/expected/timestamp.out b/src/test/regress/expected/timestamp.out
index 4927bf1db94..5f3de34149a 100644
--- a/src/test/regress/expected/timestamp.out
+++ b/src/test/regress/expected/timestamp.out
@@ -1,8 +1,6 @@
--
-- TIMESTAMP
--
--- needed so tests pass even in Australia
-SET australian_timezones = 'off';
CREATE TABLE TIMESTAMP_TBL ( d1 timestamp(2) without time zone);
-- Shorthand values
-- Not directly usable for regression testing since these are not constants.
diff --git a/src/test/regress/expected/timestamptz.out b/src/test/regress/expected/timestamptz.out
index e79ec3f5246..4448ef6e20a 100644
--- a/src/test/regress/expected/timestamptz.out
+++ b/src/test/regress/expected/timestamptz.out
@@ -1,8 +1,6 @@
--
-- TIMESTAMPTZ
--
--- needed so tests pass even in Australia
-SET australian_timezones = 'off';
CREATE TABLE TIMESTAMPTZ_TBL ( d1 timestamp(2) with time zone);
INSERT INTO TIMESTAMPTZ_TBL VALUES ('now');
INSERT INTO TIMESTAMPTZ_TBL VALUES ('current');
diff --git a/src/test/regress/pg_regress.c b/src/test/regress/pg_regress.c
index cae226111d5..3db38fd17d9 100644
--- a/src/test/regress/pg_regress.c
+++ b/src/test/regress/pg_regress.c
@@ -11,7 +11,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/test/regress/pg_regress.c,v 1.14 2006/07/25 01:37:42 adunstan Exp $
+ * $PostgreSQL: pgsql/src/test/regress/pg_regress.c,v 1.15 2006/07/25 03:51:22 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1564,8 +1564,9 @@ main(int argc, char *argv[])
"ALTER DATABASE \"%s\" SET lc_messages TO 'C';"
"ALTER DATABASE \"%s\" SET lc_monetary TO 'C';"
"ALTER DATABASE \"%s\" SET lc_numeric TO 'C';"
- "ALTER DATABASE \"%s\" SET lc_time TO 'C';",
- dbname, dbname, dbname, dbname);
+ "ALTER DATABASE \"%s\" SET lc_time TO 'C';"
+ "ALTER DATABASE \"%s\" SET timezone_abbreviations TO 'Default';",
+ dbname, dbname, dbname, dbname, dbname);
/*
* Install any requested PL languages
diff --git a/src/test/regress/sql/horology.sql b/src/test/regress/sql/horology.sql
index 922b511a864..c6d78b20cf2 100644
--- a/src/test/regress/sql/horology.sql
+++ b/src/test/regress/sql/horology.sql
@@ -1,8 +1,6 @@
--
-- HOROLOGY
--
--- needed so tests pass even in Australia
-SET australian_timezones = 'off';
SET DateStyle = 'Postgres, MDY';
--
diff --git a/src/test/regress/sql/timestamp.sql b/src/test/regress/sql/timestamp.sql
index b2c0469c83a..31235704a9c 100644
--- a/src/test/regress/sql/timestamp.sql
+++ b/src/test/regress/sql/timestamp.sql
@@ -1,8 +1,6 @@
--
-- TIMESTAMP
--
--- needed so tests pass even in Australia
-SET australian_timezones = 'off';
CREATE TABLE TIMESTAMP_TBL ( d1 timestamp(2) without time zone);
diff --git a/src/test/regress/sql/timestamptz.sql b/src/test/regress/sql/timestamptz.sql
index f5167f73eaf..65af1b04173 100644
--- a/src/test/regress/sql/timestamptz.sql
+++ b/src/test/regress/sql/timestamptz.sql
@@ -1,8 +1,6 @@
--
-- TIMESTAMPTZ
--
--- needed so tests pass even in Australia
-SET australian_timezones = 'off';
CREATE TABLE TIMESTAMPTZ_TBL ( d1 timestamp(2) with time zone);
diff --git a/src/timezone/Makefile b/src/timezone/Makefile
index d2efd71b889..69e79b8536e 100644
--- a/src/timezone/Makefile
+++ b/src/timezone/Makefile
@@ -4,7 +4,7 @@
# Makefile for the timezone library
# IDENTIFICATION
-# $PostgreSQL: pgsql/src/timezone/Makefile,v 1.23 2005/12/09 21:19:36 petere Exp $
+# $PostgreSQL: pgsql/src/timezone/Makefile,v 1.24 2006/07/25 03:51:22 tgl Exp $
#
#-------------------------------------------------------------------------
@@ -35,12 +35,14 @@ zic: $(ZICOBJS)
install: all installdirs
./zic -d '$(DESTDIR)$(datadir)/timezone' $(TZDATAFILES)
+ $(MAKE) -C tznames $@
installdirs:
$(mkinstalldirs) '$(DESTDIR)$(datadir)'
uninstall:
rm -rf '$(DESTDIR)$(datadir)/timezone'
+ $(MAKE) -C tznames $@
clean distclean maintainer-clean:
rm -f SUBSYS.o zic$(X) $(OBJS) $(ZICOBJS)
diff --git a/src/timezone/README b/src/timezone/README
index 5204ccba854..564f8e0e75f 100644
--- a/src/timezone/README
+++ b/src/timezone/README
@@ -11,3 +11,9 @@ from
Since time zone rules change frequently in some parts of the world,
we should endeavor to update the data files before each PostgreSQL
release.
+
+At each update, we should check if time zone offsets have changed.
+Just search for the current or previous year and see what has changed.
+Sometimes a country changes its time zone offsets, for example Georgia
+in 2004. Just grepping in the zic database files for 2004 is enough to
+spot such a change. Then the files under tznames/ should be updated.
diff --git a/src/timezone/tznames/Africa.txt b/src/timezone/tznames/Africa.txt
new file mode 100644
index 00000000000..ccbced3465b
--- /dev/null
+++ b/src/timezone/tznames/Africa.txt
@@ -0,0 +1,168 @@
+#
+# NOTE:
+# This file is NOT loaded by the PostgreSQL database. It just serves as
+# a template for timezones you could need. See the `Date/Time Support'
+# appendix in the PostgreSQL documentation for more information.
+#
+
+CAT 7200 # Central Africa Time
+ # (Africa/Blantyre)
+ # (Africa/Bujumbura)
+ # (Africa/Gaborone)
+ # (Africa/Harare)
+ # (Africa/Kigali)
+ # (Africa/Lubumbashi)
+ # (Africa/Lusaka)
+ # (Africa/Maputo)
+CEST 7200 D # Central Europe Summer Time
+ # (Africa/Ceuta)
+ # (Europe/Amsterdam)
+ # (Europe/Andorra)
+ # (Europe/Belgrade)
+ # (Europe/Berlin)
+ # (Europe/Brussels)
+ # (Europe/Budapest)
+ # (Europe/Copenhagen)
+ # (Europe/Gibraltar)
+ # (Europe/Luxembourg)
+ # (Europe/Madrid)
+ # (Europe/Malta)
+ # (Europe/Monaco)
+ # (Europe/Oslo)
+ # (Europe/Paris)
+ # (Europe/Prague)
+ # (Europe/Rome)
+ # (Europe/Stockholm)
+ # (Europe/Tirane)
+ # (Europe/Vaduz)
+ # (Europe/Vienna)
+ # (Europe/Warsaw)
+ # (Europe/Zurich)
+CET 3600 # Central Europe Time
+ # (Africa/Algiers)
+ # (Africa/Ceuta)
+ # (Europe/Amsterdam)
+ # (Europe/Andorra)
+ # (Europe/Belgrade)
+ # (Europe/Berlin)
+ # (Europe/Brussels)
+ # (Europe/Budapest)
+ # (Europe/Copenhagen)
+ # (Europe/Gibraltar)
+ # (Europe/Luxembourg)
+ # (Europe/Madrid)
+ # (Europe/Malta)
+ # (Europe/Monaco)
+ # (Europe/Oslo)
+ # (Europe/Paris)
+ # (Europe/Prague)
+ # (Europe/Rome)
+ # (Europe/Stockholm)
+ # (Europe/Tirane)
+ # (Europe/Vaduz)
+ # (Europe/Vienna)
+ # (Europe/Warsaw)
+ # (Europe/Zurich)
+EAT 10800 # East Africa Time
+ # (Africa/Addis_Ababa)
+ # (Africa/Asmera)
+ # (Africa/Dar_es_Salaam)
+ # (Africa/Djibouti)
+ # (Africa/Kampala)
+ # (Africa/Khartoum)
+ # (Africa/Mogadishu)
+ # (Africa/Nairobi)
+ # (Indian/Antananarivo)
+ # (Indian/Comoro)
+ # (Indian/Mayotte)
+EEST 10800 D # East-Egypt Summer Time
+ # Eastern Europe Summer Time
+ # (Africa/Cairo)
+ # (Asia/Amman)
+ # (Asia/Beirut)
+ # (Asia/Damascus)
+ # (Asia/Gaza)
+ # (Asia/Nicosia)
+ # (Europe/Athens)
+ # (Europe/Bucharest)
+ # (Europe/Chisinau)
+ # (Europe/Helsinki)
+ # (Europe/Istanbul)
+ # (Europe/Kaliningrad)
+ # (Europe/Kiev)
+ # (Europe/Minsk)
+ # (Europe/Riga)
+ # (Europe/Simferopol)
+ # (Europe/Sofia)
+ # (Europe/Tallinn)
+ # (Europe/Uzhgorod)
+ # (Europe/Vilnius)
+ # (Europe/Zaporozhye)
+EET 7200 # East-Egypt Time
+ # Eastern Europe Time
+ # (Africa/Cairo)
+ # (Africa/Tripoli)
+ # (Asia/Amman)
+ # (Asia/Beirut)
+ # (Asia/Damascus)
+ # (Asia/Gaza)
+ # (Asia/Nicosia)
+ # (Europe/Athens)
+ # (Europe/Bucharest)
+ # (Europe/Chisinau)
+ # (Europe/Helsinki)
+ # (Europe/Istanbul)
+ # (Europe/Kaliningrad)
+ # (Europe/Kiev)
+ # (Europe/Minsk)
+ # (Europe/Riga)
+ # (Europe/Simferopol)
+ # (Europe/Sofia)
+ # (Europe/Tallinn)
+ # (Europe/Uzhgorod)
+ # (Europe/Vilnius)
+ # (Europe/Zaporozhye)
+GMT 0 # Greenwich Mean Time
+ # (Africa/Abidjan)
+ # (Africa/Bamako)
+ # (Africa/Banjul)
+ # (Africa/Bissau)
+ # (Africa/Conakry)
+ # (Africa/Dakar)
+ # (Africa/Lome)
+ # (Africa/Monrovia)
+ # (Africa/Nouakchott)
+ # (Africa/Ouagadougou)
+ # (Africa/Sao_Tome)
+ # (America/Danmarkshavn)
+ # (Atlantic/Reykjavik)
+ # (Atlantic/St_Helena)
+ # (Etc/GMT)
+ # (Europe/Dublin)
+ # (Europe/London)
+SAST 7200 # South Africa Standard Time
+ # Australian South Standard Time
+ # (Africa/Maseru)
+ # (Africa/Mbabane)
+WAST 7200 D # West Africa Summer Time
+ # (Africa/Windhoek)
+WAT 3600 # West Africa Time
+ # (Africa/Bangui)
+ # (Africa/Brazzaville)
+ # (Africa/Douala)
+ # (Africa/Kinshasa)
+ # (Africa/Lagos)
+ # (Africa/Libreville)
+ # (Africa/Luanda)
+ # (Africa/Malabo)
+ # (Africa/Ndjamena)
+ # (Africa/Niamey)
+ # (Africa/Porto-Novo)
+ # (Africa/Windhoek)
+WET 0 # Western Europe Time
+ # (Africa/Casablanca)
+ # (Africa/El_Aaiun)
+ # (Atlantic/Canary)
+ # (Atlantic/Faeroe)
+ # (Atlantic/Madeira)
+ # (Europe/Lisbon)
diff --git a/src/timezone/tznames/America.txt b/src/timezone/tznames/America.txt
new file mode 100644
index 00000000000..4a27df425a2
--- /dev/null
+++ b/src/timezone/tznames/America.txt
@@ -0,0 +1,291 @@
+#
+# NOTE:
+# This file is NOT loaded by the PostgreSQL database. It just serves as
+# a template for timezones you could need. See the `Date/Time Support'
+# appendix in the PostgreSQL documentation for more information.
+#
+
+# Acre time is sometimes called Acre Standard Time (AST) which leads to a
+# conflict with AST (see below at AST)
+ACT -18000 # Acre Time
+ # (America/Eirunepe)
+ # (America/Rio_Branco)
+# CONFLICT! ACST is not unique
+# Other timezones:
+# - ACST: Central Australia Standard Time (Australia)
+ACST -14400 D # Acre Summer Time (not in zic)
+ # (America/Eirunepe)
+ # (America/Rio_Branco)
+# CONFLICT! ADT is not unique
+# Other timezones:
+# - ADT: Arabic Daylight Time (Asia)
+ADT -10800 D # Atlantic Daylight Time
+ # (America/Glace_Bay)
+ # (America/Goose_Bay)
+ # (America/Halifax)
+ # (America/Thule)
+ # (Atlantic/Bermuda)
+AKDT -28800 D # Alaska Daylight Time
+ # (America/Anchorage)
+ # (America/Juneau)
+ # (America/Nome)
+ # (America/Yakutat)
+AKST -32400 # Alaska Standard Time
+ # (America/Anchorage)
+ # (America/Juneau)
+ # (America/Nome)
+ # (America/Yakutat)
+# CONFLICT! AMST is not unique
+# Other timezones:
+# - AMST: Armenia Summer Time (Asia)
+AMST -10800 D # Amazon Summer Time
+ # (America/Campo_Grande)
+ # (America/Cuiaba)
+# CONFLICT! AMT is not unique
+# Other timezones:
+# - AMT: Armenia Time (Asia)
+AMT -14400 # Amazon Time
+ # (America/Boa_Vista)
+ # (America/Campo_Grande)
+ # (America/Cuiaba)
+ # (America/Manaus)
+ # (America/Porto_Velho)
+ART -10800 # Argentina Time (not in zic)
+# CONFLICT! AST is not unique
+# Other timezones:
+# - AST: Arabic Standard Time (Asia)
+# - AST: Al Manamah Standard Time (Asia) same offset as Arabia Standard Time
+# - AST/ACT: Acre Standard Time (America) listed as ACT
+# - AST: Anguilla Standard Time (America) same offset
+# - AST: Antigua Standard Time (America) same offset
+# - AST: Antilles Standard Time (America) same offset
+AST -14400 # Atlantic Standard Time
+ # (America/Anguilla)
+ # (America/Antigua)
+ # (America/Aruba)
+ # (America/Curacao)
+ # (America/Dominica)
+ # (America/Glace_Bay)
+ # (America/Goose_Bay)
+ # (America/Grenada)
+ # (America/Guadeloupe)
+ # (America/Halifax)
+ # (America/Martinique)
+ # (America/Montserrat)
+ # (America/Port_of_Spain)
+ # (America/Puerto_Rico)
+ # (America/Santo_Domingo)
+ # (America/St_Kitts)
+ # (America/St_Lucia)
+ # (America/St_Thomas)
+ # (America/St_Vincent)
+ # (America/Thule)
+ # (America/Tortola)
+ # (Atlantic/Bermuda)
+BOT -14400 # Bolivia Time
+ # (America/La_Paz)
+BRA -10800 # Brazil Time (not in zic)
+BRST -7200 D # Brasil Summer Time
+ # (America/Sao_Paulo)
+BRT -10800 # Brasil Time
+ # (America/Araguaina)
+ # (America/Bahia)
+ # (America/Belem)
+ # (America/Fortaleza)
+ # (America/Maceio)
+ # (America/Recife)
+ # (America/Sao_Paulo)
+# CONFLICT! CDT is not unique
+# Other timezones:
+# - CDT: Central Daylight Time (America)
+# - CDT: Mexico Central Daylight Time (America)
+# - CDT: Canada Central Daylight Time (America)
+CDT -14400 D # Cuba Central Daylight Time
+ # (America/Havana)
+# CONFLICT! CDT is not unique
+# Other timezones:
+# - CDT: Mexico Central Daylight Time (America)
+# - CDT: Cuba Central Daylight Time (America)
+# - CDT: Canada Central Daylight Time (America)
+CDT -18000 D # Central Daylight Time
+ # (America/Cancun)
+ # (America/Chicago)
+ # (America/Menominee)
+ # (America/Merida)
+ # (America/Mexico_City)
+ # (America/Monterrey)
+ # (America/North_Dakota/Center)
+ # (America/Rainy_River)
+ # (America/Rankin_Inlet)
+ # (America/Winnipeg)
+CLST -10800 D # Chile Summer Time
+ # (America/Santiago)
+ # (Antarctica/Palmer)
+CLT -14400 # Chile Time
+ # (America/Santiago)
+ # (Antarctica/Palmer)
+COT -18000 # Columbia Time (not in zic)
+# CONFLICT! CST is not unique
+# Other timezones:
+# - CST: Central Standard Time (Australia)
+# - CST: Central Standard Time (America)
+CST -18000 # Cuba Central Standard Time (America)
+ # (America/Havana)
+# CONFLICT! CST is not unique
+# Other timezones:
+# - CST: Central Standard Time (Australia)
+# - CST: Cuba Central Standard Time (America)
+CST -21600 # Central Standard Time (America)
+ # (America/Cancun)
+ # (America/Chicago)
+ # (America/Menominee)
+ # (America/Merida)
+ # (America/Mexico_City)
+ # (America/Monterrey)
+ # (America/North_Dakota/Center)
+ # (America/Rainy_River)
+ # (America/Rankin_Inlet)
+ # (America/Regina)
+ # (America/Swift_Current)
+ # (America/Winnipeg)
+ECT -18000 # Ecuador Time
+ # Eastern Caribbean Time
+ # (America/Guayaquil)
+EDT -14400 D # Eastern Daylight Saving Time
+ # (America/Detroit)
+ # (America/Grand_Turk)
+ # (America/Indiana/Indianapolis)
+ # (America/Indiana/Knox)
+ # (America/Indiana/Marengo)
+ # (America/Indiana/Vevay)
+ # (America/Iqaluit)
+ # (America/Kentucky/Louisville)
+ # (America/Kentucky/Monticello)
+ # (America/Montreal)
+ # (America/Nassau)
+ # (America/New_York)
+ # (America/Nipigon)
+ # (America/Pangnirtung)
+ # (America/Thunder_Bay)
+ # (America/Toronto)
+EGST 0 D # East Greenland Summer Time
+ # (America/Scoresbysund)
+EGT -3600 # East Greenland Time (Svalbard & Jan Mayen)
+ # (America/Scoresbysund)
+# CONFLICT! EST is not unique
+# Other timezones:
+# - EST: Eastern Standard Time (Australia)
+EST -18000 # Eastern Standard Time (America)
+ # (America/Cayman)
+ # (America/Coral_Harbour)
+ # (America/Detroit)
+ # (America/Grand_Turk)
+ # (America/Indiana/Indianapolis)
+ # (America/Indiana/Knox)
+ # (America/Indiana/Marengo)
+ # (America/Indiana/Vevay)
+ # (America/Iqaluit)
+ # (America/Jamaica)
+ # (America/Kentucky/Louisville)
+ # (America/Kentucky/Monticello)
+ # (America/Montreal)
+ # (America/Nassau)
+ # (America/New_York)
+ # (America/Nipigon)
+ # (America/Panama)
+ # (America/Pangnirtung)
+ # (America/Thunder_Bay)
+ # (America/Toronto)
+FNT -7200 # Fernando de Noronha Time
+ # (America/Noronha)
+FNST -3600 D # Fernando de Noronha Summer Time (not in zic)
+ # (America/Noronha)
+GFT -10800 # French Guiana Time
+ # (America/Cayenne)
+GMT 0 # Greenwich Mean Time
+ # (Africa/Abidjan)
+ # (Africa/Bamako)
+ # (Africa/Banjul)
+ # (Africa/Bissau)
+ # (Africa/Conakry)
+ # (Africa/Dakar)
+ # (Africa/Lome)
+ # (Africa/Monrovia)
+ # (Africa/Nouakchott)
+ # (Africa/Ouagadougou)
+ # (Africa/Sao_Tome)
+ # (America/Danmarkshavn)
+ # (Atlantic/Reykjavik)
+ # (Atlantic/St_Helena)
+ # (Etc/GMT)
+ # (Europe/Dublin)
+ # (Europe/London)
+GYT -14400 # Guyana Time
+ # (America/Guyana)
+HADT -32400 D # Hawaii-Aleutain Daylight Time
+ # (America/Adak)
+HAST -36000 # Hawaii-Aleutain Standard Time
+ # (America/Adak)
+MDT -21600 D # Mexico Mountain Daylight Time
+ # Mountain Daylight Time
+ # (America/Boise)
+ # (America/Cambridge_Bay)
+ # (America/Chihuahua)
+ # (America/Denver)
+ # (America/Edmonton)
+ # (America/Inuvik)
+ # (America/Mazatlan)
+ # (America/Yellowknife)
+MST -25200 # Mexico Mountain Standard Time
+ # Mountain Standard Time
+ # (America/Boise)
+ # (America/Cambridge_Bay)
+ # (America/Chihuahua)
+ # (America/Dawson_Creek)
+ # (America/Denver)
+ # (America/Edmonton)
+ # (America/Hermosillo)
+ # (America/Inuvik)
+ # (America/Mazatlan)
+ # (America/Phoenix)
+ # (America/Yellowknife)
+NDT -9000 D # Newfoundland Daylight Time
+ # (America/St_Johns)
+# CONFLICT! NFT is not unique
+# Other timezones:
+# - NFT: Norfolk Time (Pacific)
+NFT -12600 # Newfoundland Time (not in zic)
+NST -12600 # Newfoundland Standard Time
+ # (America/St_Johns)
+PDT -25200 D # Pacific Daylight Time
+ # (America/Dawson)
+ # (America/Los_Angeles)
+ # (America/Tijuana)
+ # (America/Vancouver)
+ # (America/Whitehorse)
+PET -18000 # Peru Time (not in zic)
+PMDT -7200 D # Pierre & Miquelon Daylight Time
+ # (America/Miquelon)
+PMST -10800 # Pierre & Miquelon Standard Time
+ # (America/Miquelon)
+PST -28800 # Pacific Standard Time
+ # (America/Dawson)
+ # (America/Los_Angeles)
+ # (America/Tijuana)
+ # (America/Vancouver)
+ # (America/Whitehorse)
+ # (Pacific/Pitcairn)
+PYST -10800 D # Paraguay Summer Time
+ # (America/Asuncion)
+PYT -14400 # Paraguay Time
+ # (America/Asuncion)
+SRT -10800 # Suriname Time
+ # (America/Paramaribo)
+UYST -7200 D # Uruguay Summer Time (not in zic)
+UYT -10800 # Uruguay Time (not in zic)
+VET -14400 # Venezuela Time
+ # (America/Caracas)
+WGST -7200 D # Western Greenland Summer Time
+ # (America/Godthab)
+WGT -10800 # West Greenland Time
+ # (America/Godthab)
diff --git a/src/timezone/tznames/Antarctica.txt b/src/timezone/tznames/Antarctica.txt
new file mode 100644
index 00000000000..6f3069f1b3e
--- /dev/null
+++ b/src/timezone/tznames/Antarctica.txt
@@ -0,0 +1,37 @@
+#
+# NOTE:
+# This file is NOT loaded by the PostgreSQL database. It just serves as
+# a template for timezones you could need. See the `Date/Time Support'
+# appendix in the PostgreSQL documentation for more information.
+#
+
+CLST -10800 D # Chile Summer Time
+ # (America/Santiago)
+ # (Antarctica/Palmer)
+CLT -14400 # Chile Time
+ # (America/Santiago)
+ # (Antarctica/Palmer)
+DAVT 25200 # Davis Time (Antarctica)
+ # (Antarctica/Davis)
+DDUT 36000 # Dumont-d`Urville Time (Antarctica)
+ # (Antarctica/DumontDUrville)
+MAWT 21600 # Mawson Time (Antarctica)
+ # (Antarctica/Mawson)
+NZDT 46800 D # New Zealand Daylight Time
+ # (Antarctica/McMurdo)
+ # (Pacific/Auckland)
+NZST 43200 # New Zealand Standard Time
+ # (Antarctica/McMurdo)
+ # (Pacific/Auckland)
+ROTT -10800 # Rothera Time
+ # (Antarctica/Rothera)
+SYOT 10800 # Syowa Time
+ # (Antarctica/Syowa)
+VOST 21600 # Vostok time
+ # (Antarctica/Vostok)
+# CONFLICT! WST is not unique
+# Other timezones:
+# - WST: West Samoa Time
+WST 28800 # Western Standard Time (Australia)
+ # (Antarctica/Casey)
+ # (Australia/Perth)
diff --git a/src/timezone/tznames/Asia.txt b/src/timezone/tznames/Asia.txt
new file mode 100644
index 00000000000..70c3a2e28ea
--- /dev/null
+++ b/src/timezone/tznames/Asia.txt
@@ -0,0 +1,236 @@
+#
+# NOTE:
+# This file is NOT loaded by the PostgreSQL database. It just serves as
+# a template for timezones you could need. See the `Date/Time Support'
+# appendix in the PostgreSQL documentation for more information.
+#
+
+# CONFLICT! ADT is not unique
+# Other timezones:
+# - ADT: Atlantic Daylight Time (America)
+ADT 14400 D # Arabia Daylight Time
+ # (Asia/Baghdad)
+AFT 16200 # Afghanistan Time
+ # (Asia/Kabul)
+ALMST 25200 D # Alma-Ata Summer Time
+ # (Asia/Almaty)
+ALMT 21600 # Alma-Ata Time
+ # (Asia/Almaty)
+# CONFLICT! AMST is not unique
+# Other timezones:
+# - AMST: Amazon Summer Time (America)
+AMST 18000 D # Armenia Summer Time
+ # (Asia/Yerevan)
+# CONFLICT! AMT is not unique
+# Other timezones:
+# - AMT: Amazon Time (America)
+AMT 14400 # Armenia Time
+ # (Asia/Yerevan)
+ANAST 46800 D # Anadyr Summer Time
+ # (Asia/Anadyr)
+ANAT 43200 # Anadyr Time
+ # (Asia/Anadyr)
+AQTT 18000 # Aqtau Time
+ # Aqtobe Time
+ # (Asia/Aqtau)
+ # (Asia/Aqtobe)
+# CONFLICT! AST is not unique
+# Other timezones:
+# - AST: Atlantic Standard Time (America)
+# - AST/ACT: Acre Standard Time (America) listed as ACT
+# - AST: Anguilla Standard Time (America) same offset as Atlantic Standard Time
+# - AST: Antigua Standard Time (America) same offset as Atlantic Standard Time
+# - AST: Antilles Standard Time (America) same offset as Atlantic Standard Time
+# - AST: Al Manamah Standard Time (Asia) same offset as Arabia Standard Time
+AST 10800 # Arabia Standard Time
+ # (Asia/Aden)
+ # (Asia/Baghdad)
+ # (Asia/Bahrain)
+ # (Asia/Kuwait)
+ # (Asia/Qatar)
+ # (Asia/Riyadh)
+AZST 18000 D # Azerbaijan Summer Time
+ # (Asia/Baku)
+AZT 14400 # Azerbaijan Time
+ # (Asia/Baku)
+BDT 21600 # Bangladesh Time
+ # (Asia/Dhaka)
+BNT 28800 # Brunei Darussalam Time
+ # (Asia/Brunei)
+BORT 28800 # Borneo Time (Indonesia) (not in zic)
+BTT 21600 # Bhutan Time
+ # (Asia/Thimphu)
+CCT 28800 # China Coastal Time (not in zic)
+CHOST 36000 D # Choibalsan Summer Time
+ # (Asia/Choibalsan)
+CHOT 32400 # Choibalsan Time
+ # (Asia/Choibalsan)
+CIT 28800 # Central Indonesia Time
+ # (Asia/Makassar)
+EEST 10800 D # East-Egypt Summer Time
+ # Eastern Europe Summer Time
+ # (Africa/Cairo)
+ # (Asia/Amman)
+ # (Asia/Beirut)
+ # (Asia/Damascus)
+ # (Asia/Gaza)
+ # (Asia/Nicosia)
+ # (Europe/Athens)
+ # (Europe/Bucharest)
+ # (Europe/Chisinau)
+ # (Europe/Helsinki)
+ # (Europe/Istanbul)
+ # (Europe/Kaliningrad)
+ # (Europe/Kiev)
+ # (Europe/Minsk)
+ # (Europe/Riga)
+ # (Europe/Simferopol)
+ # (Europe/Sofia)
+ # (Europe/Tallinn)
+ # (Europe/Uzhgorod)
+ # (Europe/Vilnius)
+ # (Europe/Zaporozhye)
+EET 7200 # East-Egypt Time
+ # Eastern Europe Time
+ # (Africa/Cairo)
+ # (Africa/Tripoli)
+ # (Asia/Amman)
+ # (Asia/Beirut)
+ # (Asia/Damascus)
+ # (Asia/Gaza)
+ # (Asia/Nicosia)
+ # (Europe/Athens)
+ # (Europe/Bucharest)
+ # (Europe/Chisinau)
+ # (Europe/Helsinki)
+ # (Europe/Istanbul)
+ # (Europe/Kaliningrad)
+ # (Europe/Kiev)
+ # (Europe/Minsk)
+ # (Europe/Riga)
+ # (Europe/Simferopol)
+ # (Europe/Sofia)
+ # (Europe/Tallinn)
+ # (Europe/Uzhgorod)
+ # (Europe/Vilnius)
+ # (Europe/Zaporozhye)
+EIT 32400 # East Indonesia Time
+ # (Asia/Jayapura)
+GEST 14400 D # Georgia Summer Time (there was a timezone change in 2004)
+ # (Asia/Tbilisi)
+GET 10800 # Georgia Time (there was a timezone change in 2004)
+ # (Asia/Tbilisi)
+# CONFLICT! GST is not unique
+# Other timezones:
+# - GST: South Georgia Time (Atlantic)
+GST 14400 # Gulf Standard Time
+ # (Asia/Dubai)
+ # (Asia/Muscat)
+HKT 28800 # Hong Kong Time (not in zic)
+HOVST 28800 D # Hovd Summer Time
+ # (Asia/Hovd)
+HOVT 25200 # Hovd Time
+ # (Asia/Hovd)
+ICT 25200 # Indochina Time
+ # (Asia/Bangkok)
+ # (Asia/Phnom_Penh)
+ # (Asia/Saigon)
+ # (Asia/Vientiane)
+IRKST 32400 D # Irkutsk Summer Time
+ # (Asia/Irkutsk)
+IRKT 28800 # Irkutsk Time
+ # (Asia/Irkutsk)
+IRT 12600 # Iran Time (not in zic)
+# CONFLICT! IST is not unique
+# Other timezones:
+# - IST: Irish Summer Time (Europe)
+# - IST: Israel Standard Time (Asia)
+IST 19800 # Indian Standard Time
+ # (Asia/Calcutta)
+# CONFLICT! IST is not unique
+# Other timezones:
+# - IST: Irish Summer Time (Europe)
+# - IST: Indian Standard Time (Asia)
+IST 7200 # Israel Standard Time
+ # (this time zone is not contained in the ZIC database)
+JAYT 32400 # Jayapura Time (Indonesia) (not in zic)
+KDT 36000 D # Korean Daylight Time (not in zic)
+KGST 21600 D # Kyrgyzstan Summer Time
+ # (Asia/Bishkek)
+KGT 18000 # Kyrgyzstan Time
+ # (Asia/Bishkek)
+KRAST 28800 D # Krasnoyarsk Summer Time
+ # (Asia/Krasnoyarsk)
+KRAT 25200 # Krasnoyarsk Time
+ # (Asia/Krasnoyarsk)
+KST 32400 # Korean Standard Time
+ # (Asia/Pyongyang)
+LKT 21600 # Lanka Time
+ # (Asia/Colombo)
+MAGST 43200 D # Magadan Summer Time
+ # (Asia/Magadan)
+MAGT 39600 # Magadan Time
+ # (Asia/Magadan)
+MMT 23400 # Myanmar Time
+ # (Asia/Rangoon)
+MYT 28800 # Malaysia Time
+ # (Asia/Kuala_Lumpur)
+ # (Asia/Kuching)
+NOVST 25200 D # Novosibirsk Summer Time
+ # (Asia/Novosibirsk)
+NOVT 21600 # Novosibirsk Time
+ # (Asia/Novosibirsk)
+NPT 20700 # Nepal Time
+ # (Asia/Katmandu)
+OMSST 25200 D # Omsk Summer Time
+ # (Asia/Omsk)
+OMST 21600 # Omsk Time
+ # (Asia/Omsk)
+ORAT 18000 # Oral Time
+ # (Asia/Oral)
+PETST 46800 D # Petropavlovsk-Kamchatski Summer Time
+ # (Asia/Kamchatka)
+PETT 43200 # Petropavlovsk-Kamchatski Time
+ # (Asia/Kamchatka)
+PHT 28800 # Phillipine Time (not in zic)
+PKT 18000 # Pakistan Time (not in zic)
+QYZT 21600 # Kizilorda Time
+ # (Asia/Qyzylorda)
+SAKST 39600 D # Sakhalin Summer Time
+ # (Asia/Sakhalin)
+SAKT 36000 # Sakhalin Time
+ # (Asia/Sakhalin)
+SGT 28800 # Singapore Time
+ # (Asia/Singapore)
+TJT 18000 # Tajikistan Time
+ # (Asia/Dushanbe)
+TLT 32400 # East Timor Time
+ # (Asia/Dili)
+TMT 18000 # Turkmenistan Time
+ # (Asia/Ashgabat)
+ULAST 32400 D # Ulan Bator Summer Time
+ # (Asia/Ulaanbaatar)
+ULAT 28800 # Ulan Bator Time
+ # (Asia/Ulaanbaatar)
+UZST 21600 D # Uzbekistan Summer Time
+ # (Asia/Samarkand)
+ # (Asia/Tashkent)
+UZT 18000 # Uzbekistan Time
+ # (Asia/Samarkand)
+ # (Asia/Tashkent)
+VLAST 39600 D # Vladivostok Summer Time
+ # (Asia/Vladivostok)
+VLAT 36000 # Vladivostok Time
+ # (Asia/Vladivostok)
+WIT 25200 # Waktu Indonesia Timur
+ # West Indonesia Time
+ # (Asia/Jakarta)
+ # (Asia/Pontianak)
+YAKST 36000 D # Yakutsk Summer Time
+ # (Asia/Yakutsk)
+YAKT 32400 # Yakutsk Time
+ # (Asia/Yakutsk)
+YEKST 21600 D # Yekaterinburg Summer Time
+ # (Asia/Yekaterinburg)
+YEKT 18000 # Yekaterinburg Time
+ # (Asia/Yekaterinburg)
diff --git a/src/timezone/tznames/Atlantic.txt b/src/timezone/tznames/Atlantic.txt
new file mode 100644
index 00000000000..5c447d9c92e
--- /dev/null
+++ b/src/timezone/tznames/Atlantic.txt
@@ -0,0 +1,92 @@
+#
+# NOTE:
+# This file is NOT loaded by the PostgreSQL database. It just serves as
+# a template for timezones you could need. See the `Date/Time Support'
+# appendix in the PostgreSQL documentation for more information.
+#
+
+# CONFLICT! ADT is not unique
+# Other timezones:
+# - ADT: Arabic Daylight Time (Asia)
+ADT -10800 D # Atlantic Daylight Time
+ # (America/Glace_Bay)
+ # (America/Goose_Bay)
+ # (America/Halifax)
+ # (America/Thule)
+ # (Atlantic/Bermuda)
+# CONFLICT! AST is not unique
+# Other timezones:
+# - AST: Arabic Standard Time (Asia)
+# - AST: Al Manamah Standard Time (Asia) same offset as Arabia Standard Time
+# - AST/ACT: Acre Standard Time (America) listed as ACT
+# - AST: Anguilla Standard Time (America) same offset
+# - AST: Antigua Standard Time (America) same offset
+# - AST: Antilles Standard Time (America) same offset
+AST -14400 # Atlantic Standard Time
+ # (America/Anguilla)
+ # (America/Antigua)
+ # (America/Aruba)
+ # (America/Curacao)
+ # (America/Dominica)
+ # (America/Glace_Bay)
+ # (America/Goose_Bay)
+ # (America/Grenada)
+ # (America/Guadeloupe)
+ # (America/Halifax)
+ # (America/Martinique)
+ # (America/Montserrat)
+ # (America/Port_of_Spain)
+ # (America/Puerto_Rico)
+ # (America/Santo_Domingo)
+ # (America/St_Kitts)
+ # (America/St_Lucia)
+ # (America/St_Thomas)
+ # (America/St_Vincent)
+ # (America/Thule)
+ # (America/Tortola)
+ # (Atlantic/Bermuda)
+AZOST 0 D # Azores Summer Time
+ # (Atlantic/Azores)
+AZOT -3600 # Azores Time
+ # (Atlantic/Azores)
+CVT -3600 # Cape Verde Time
+ # (Atlantic/Cape_Verde)
+FKST -10800 D # Falkland Islands Summer Time
+ # (Atlantic/Stanley)
+FKT -14400 # Falkland Islands Time
+ # (Atlantic/Stanley)
+GMT 0 # Greenwich Mean Time
+ # (Africa/Abidjan)
+ # (Africa/Bamako)
+ # (Africa/Banjul)
+ # (Africa/Bissau)
+ # (Africa/Conakry)
+ # (Africa/Dakar)
+ # (Africa/Lome)
+ # (Africa/Monrovia)
+ # (Africa/Nouakchott)
+ # (Africa/Ouagadougou)
+ # (Africa/Sao_Tome)
+ # (America/Danmarkshavn)
+ # (Atlantic/Reykjavik)
+ # (Atlantic/St_Helena)
+ # (Etc/GMT)
+ # (Europe/Dublin)
+ # (Europe/London)
+# CONFLICT! GST is not unique
+# Other timezones:
+# - GST: Gulf Standard Time (Asia)
+GST -7200 # South Georgia Time (Atlantic)
+ # (Atlantic/South_Georgia)
+WEST 3600 D # Western Europe Summer Time
+ # (Atlantic/Canary)
+ # (Atlantic/Faeroe)
+ # (Atlantic/Madeira)
+ # (Europe/Lisbon)
+WET 0 # Western Europe Time
+ # (Africa/Casablanca)
+ # (Africa/El_Aaiun)
+ # (Atlantic/Canary)
+ # (Atlantic/Faeroe)
+ # (Atlantic/Madeira)
+ # (Europe/Lisbon)
diff --git a/src/timezone/tznames/Australia b/src/timezone/tznames/Australia
new file mode 100644
index 00000000000..a47d5d33868
--- /dev/null
+++ b/src/timezone/tznames/Australia
@@ -0,0 +1,33 @@
+# Time zone configuration file for set "Australia"
+
+# In order to use this file, you need to set the run-time parameter
+# timezone_abbreviations to 'Australia'. See the `Date/Time Support'
+# appendix in the PostgreSQL documentation for more information.
+
+
+# include the default set
+@INCLUDE Default
+
+# most timezones are already defined in the default set. With the OVERRIDE
+# option, PostgreSQL will use the new definitions instead of throwing an error
+# in case of a conflict.
+@OVERRIDE
+
+ACST 34200 # Central Australia Standard Time (not in zic)
+CST 34200 # Central Standard Time (Australia)
+ # (Australia/Adelaide)
+ # (Australia/Broken_Hill)
+EAST 36000 # East Australian Standard Time (Australia) (not in zic)
+EST 36000 # Eastern Standard Time (Australia)
+ # (Australia/Currie)
+ # (Australia/Hobart)
+ # (Australia/Melbourne)
+ # (Australia/Sydney)
+ # (Australia/Currie)
+ # (Australia/Hobart)
+ # (Australia/Melbourne)
+ # (Australia/Sydney)
+SAT 34200 # South Australian Standard Time (not in zic)
+WST 28800 # Western Standard Time (Australia)
+ # (Antarctica/Casey)
+ # (Australia/Perth)
diff --git a/src/timezone/tznames/Australia.txt b/src/timezone/tznames/Australia.txt
new file mode 100644
index 00000000000..0fdad5d1c9e
--- /dev/null
+++ b/src/timezone/tznames/Australia.txt
@@ -0,0 +1,59 @@
+#
+# NOTE:
+# This file is NOT loaded by the PostgreSQL database. It just serves as
+# a template for timezones you could need. See the `Date/Time Support'
+# appendix in the PostgreSQL documentation for more information.
+#
+
+ACSST 37800 D # Central Australia (not in zic)
+# CONFLICT! ACST is not unique
+# Other timezones:
+# - ACST: Acre Summer Time (America)
+ACST 34200 # Central Australia Standard Time (not in zic)
+AESST 39600 D # Australia Eastern Summer Standard Time (not in zic)
+AEST 36000 # Australia Eastern Standard Time (not in zic)
+AWSST 32400 D # Australia Western Summer Standard Time (not in zic)
+AWST 28800 # Australia Western Standard Time (not in zic)
+CADT 37800 D # Central Australia Daylight-Saving Time (not in zic)
+CAST 34200 # Central Australia Standard Time (not in zic)
+# CONFLICT! CST is not unique
+# Other timezones:
+# - CST: Central Standard Time (America)
+# - CST: Cuba Central Standard Time (America)
+CST 34200 # Central Standard Time (Australia)
+ # (Australia/Adelaide)
+ # (Australia/Broken_Hill)
+# CONFLICT! EAST is not unique
+# Other timezones:
+# - EAST: Easter Island Time (Chile) (Pacific)
+EAST 36000 # East Australian Standard Time (not in zic)
+# CONFLICT! EST is not unique
+# Other timezones:
+# - EST: Eastern Standard Time (America)
+EST 36000 # Eastern Standard Time (Australia)
+ # (Australia/Currie)
+ # (Australia/Hobart)
+ # (Australia/Melbourne)
+ # (Australia/Sydney)
+ # (Australia/Currie)
+ # (Australia/Hobart)
+ # (Australia/Melbourne)
+ # (Australia/Sydney)
+LHDT 39600 D # Lord Howe Daylight Time, Australia (not in zic)
+LHST 37800 # Lord Howe Standard Time (Australia)
+ # (Australia/Lord_Howe)
+LIGT 36000 # Melbourne, Australia (not in zic)
+NZT 43200 # New Zealand Time (not in zic)
+SADT 37800 D # South Australian Daylight-Saving Time (not in zic)
+SAST 34200 # South Australian Standard Time (not in zic)
+SAT 34200 # South Australian Standard Time (not in zic)
+WADT 28800 D # West Australian Daylight-Saving Time (not in zic)
+WAST 25200 # West Australian Standard Time (not in zic)
+WDT 32400 D # West Australian Daylight-Saving Time (not in zic)
+# CONFLICT! WST is not unique
+# Other timezones:
+# - WST: West Samoa Time
+WST 28800 # Western Standard Time (Australia)
+ # (Antarctica/Casey)
+ # (Australia/Perth)
+
diff --git a/src/timezone/tznames/Default b/src/timezone/tznames/Default
new file mode 100644
index 00000000000..dfadd22af13
--- /dev/null
+++ b/src/timezone/tznames/Default
@@ -0,0 +1,702 @@
+# Time zone configuration file for set "Default"
+
+# In order to use this file, you need to set the run-time parameter
+# timezone_abbreviations to 'Default'. See the `Date/Time Support'
+# appendix in the PostgreSQL documentation for more information.
+
+
+#################### AFRICA ####################
+
+EAT 10800 # East Africa Time
+ # (Africa/Addis_Ababa)
+ # (Africa/Asmera)
+ # (Africa/Dar_es_Salaam)
+ # (Africa/Djibouti)
+ # (Africa/Kampala)
+ # (Africa/Khartoum)
+ # (Africa/Mogadishu)
+ # (Africa/Nairobi)
+ # (Indian/Antananarivo)
+ # (Indian/Comoro)
+ # (Indian/Mayotte)
+WAT 3600 # West Africa Time
+ # (Africa/Bangui)
+ # (Africa/Brazzaville)
+ # (Africa/Douala)
+ # (Africa/Kinshasa)
+ # (Africa/Lagos)
+ # (Africa/Libreville)
+ # (Africa/Luanda)
+ # (Africa/Malabo)
+ # (Africa/Ndjamena)
+ # (Africa/Niamey)
+ # (Africa/Porto-Novo)
+ # (Africa/Windhoek)
+
+#################### AMERICA ####################
+
+# Acre time is sometimes called Acre Standard Time (AST) which leads to a
+# conflict with AST (see below at AST)
+ACT -18000 # Acre Time
+ # (America/Eirunepe)
+ # (America/Rio_Branco)
+ACST -14400 D # Acre Summer Time
+ # (America/Eirunepe)
+ # (America/Rio_Branco)
+AKDT -28800 D # Alaska Daylight Time
+ # (America/Anchorage)
+ # (America/Juneau)
+ # (America/Nome)
+ # (America/Yakutat)
+AKST -32400 # Alaska Standard Time
+ # (America/Anchorage)
+ # (America/Juneau)
+ # (America/Nome)
+ # (America/Yakutat)
+ART -10800 # Argentina Time (not in zic)
+BOT -14400 # Bolivia Time
+ # (America/La_Paz)
+BRA -10800 # Brazil Time (not in zic)
+BRST -7200 D # Brasil Summer Time
+ # (America/Sao_Paulo)
+BRT -10800 # Brasil Time
+ # (America/Araguaina)
+ # (America/Bahia)
+ # (America/Belem)
+ # (America/Fortaleza)
+ # (America/Maceio)
+ # (America/Recife)
+ # (America/Sao_Paulo)
+COT -18000 # Columbia Time (not in zic)
+# CONFLICT! CDT is not unique
+# Other timezones:
+# - CDT: Mexico Central Daylight Time (America)
+# - CDT: Cuba Central Daylight Time (America)
+# - CDT: Canada Central Daylight Time (America)
+CDT -18000 D # Central Daylight Time
+ # (America/Cancun)
+ # (America/Chicago)
+ # (America/Menominee)
+ # (America/Merida)
+ # (America/Mexico_City)
+ # (America/Monterrey)
+ # (America/North_Dakota/Center)
+ # (America/Rainy_River)
+ # (America/Rankin_Inlet)
+ # (America/Winnipeg)
+CLST -10800 D # Chile Summer Time
+ # (America/Santiago)
+ # (Antarctica/Palmer)
+CLT -14400 # Chile Time
+ # (America/Santiago)
+ # (Antarctica/Palmer)
+# CONFLICT! CST is not unique
+# Other timezones:
+# - CST: Central Standard Time (Australia)
+# - CST: Cuba Central Standard Time (America)
+CST -21600 # Central Standard Time (America)
+ # (America/Cancun)
+ # (America/Chicago)
+ # (America/Menominee)
+ # (America/Merida)
+ # (America/Mexico_City)
+ # (America/Monterrey)
+ # (America/North_Dakota/Center)
+ # (America/Rainy_River)
+ # (America/Rankin_Inlet)
+ # (America/Regina)
+ # (America/Swift_Current)
+ # (America/Winnipeg)
+EDT -14400 D # Eastern Daylight Saving Time
+ # (America/Detroit)
+ # (America/Grand_Turk)
+ # (America/Indiana/Indianapolis)
+ # (America/Indiana/Knox)
+ # (America/Indiana/Marengo)
+ # (America/Indiana/Vevay)
+ # (America/Iqaluit)
+ # (America/Kentucky/Louisville)
+ # (America/Kentucky/Monticello)
+ # (America/Montreal)
+ # (America/Nassau)
+ # (America/New_York)
+ # (America/Nipigon)
+ # (America/Pangnirtung)
+ # (America/Thunder_Bay)
+ # (America/Toronto)
+EGST 0 D # East Greenland Summer Time
+ # (America/Scoresbysund)
+EGT -3600 # East Greenland Time (Svalbard & Jan Mayen)
+ # (America/Scoresbysund)
+# CONFLICT! EST is not unique
+# Other timezones:
+# - EST: Eastern Standard Time (Australia)
+EST -18000 # Eastern Standard Time (America)
+ # (America/Cayman)
+ # (America/Coral_Harbour)
+ # (America/Detroit)
+ # (America/Grand_Turk)
+ # (America/Indiana/Indianapolis)
+ # (America/Indiana/Knox)
+ # (America/Indiana/Marengo)
+ # (America/Indiana/Vevay)
+ # (America/Iqaluit)
+ # (America/Jamaica)
+ # (America/Kentucky/Louisville)
+ # (America/Kentucky/Monticello)
+ # (America/Montreal)
+ # (America/Nassau)
+ # (America/New_York)
+ # (America/Nipigon)
+ # (America/Panama)
+ # (America/Pangnirtung)
+ # (America/Thunder_Bay)
+ # (America/Toronto)
+FNT -7200 # Fernando de Noronha Time
+ # (America/Noronha)
+FNST -3600 D # Fernando de Noronha Summer Time (not in zic)
+ # (America/Noronha)
+GFT -10800 # French Guiana Time
+ # (America/Cayenne)
+GYT -14400 # Guyana Time
+ # (America/Guyana)
+MDT -21600 D # Mexico Mountain Daylight Time
+ # Mountain Daylight Time
+ # (America/Boise)
+ # (America/Cambridge_Bay)
+ # (America/Chihuahua)
+ # (America/Denver)
+ # (America/Edmonton)
+ # (America/Inuvik)
+ # (America/Mazatlan)
+ # (America/Yellowknife)
+MST -25200 # Mexico Mountain Standard Time
+ # Mountain Standard Time
+ # (America/Boise)
+ # (America/Cambridge_Bay)
+ # (America/Chihuahua)
+ # (America/Dawson_Creek)
+ # (America/Denver)
+ # (America/Edmonton)
+ # (America/Hermosillo)
+ # (America/Inuvik)
+ # (America/Mazatlan)
+ # (America/Phoenix)
+ # (America/Yellowknife)
+NDT -9000 D # Newfoundland Daylight Time
+ # (America/St_Johns)
+NST -12600 # Newfoundland Standard Time
+ # (America/St_Johns)
+PET -18000 # Peru Time (not in zic)
+PDT -25200 D # Pacific Daylight Time
+ # (America/Dawson)
+ # (America/Los_Angeles)
+ # (America/Tijuana)
+ # (America/Vancouver)
+ # (America/Whitehorse)
+PMDT -7200 D # Pierre & Miquelon Daylight Time
+ # (America/Miquelon)
+PMST -10800 # Pierre & Miquelon Standard Time
+ # (America/Miquelon)
+PST -28800 # Pacific Standard Time
+ # (America/Dawson)
+ # (America/Los_Angeles)
+ # (America/Tijuana)
+ # (America/Vancouver)
+ # (America/Whitehorse)
+ # (Pacific/Pitcairn)
+PYST -10800 D # Paraguay Summer Time
+ # (America/Asuncion)
+PYT -14400 # Paraguay Time
+ # (America/Asuncion)
+UYST -7200 D # Uruguay Summer Time (not in zic)
+UYT -10800 # Uruguay Time (not in zic)
+VET -14400 # Venezuela Time
+ # (America/Caracas)
+WGST -7200 D # Western Greenland Summer Time
+ # (America/Godthab)
+WGT -10800 # West Greenland Time
+ # (America/Godthab)
+
+#################### ANTARCTICA ####################
+
+DAVT 25200 # Davis Time (Antarctica)
+ # (Antarctica/Davis)
+DDUT 36000 # Dumont-d'Urville Time (Antarctica)
+ # (Antarctica/DumontDUrville)
+ # (Antarctica/Palmer)
+ # (America/Santiago)
+MAWT 21600 # Mawson Time (Antarctica)
+ # (Antarctica/Mawson)
+
+#################### ASIA ####################
+
+AFT 16200 # Afghanistan Time
+ # (Asia/Kabul)
+ALMT 21600 # Alma-Ata Time
+ # (Asia/Almaty)
+ALMST 25200 D # Alma-Ata Summer Time
+ # (Asia/Almaty)
+AMST 18000 D # Armenia Summer Time
+ # (Asia/Yerevan)
+# CONFLICT! AMT is not unique
+# Other timezones:
+# - AMT: Amazon Time (America)
+AMT 14400 # Armenia Time
+ # (Asia/Yerevan)
+ANAST 46800 D # Anadyr Summer Time
+ # (Asia/Anadyr)
+ANAT 43200 # Anadyr Time
+ # (Asia/Anadyr)
+AZST 18000 D # Azerbaijan Summer Time
+ # (Asia/Baku)
+AZT 14400 # Azerbaijan Time
+ # (Asia/Baku)
+BDT 21600 # Bangladesh Time
+ # (Asia/Dhaka)
+BNT 28800 # Brunei Darussalam Time
+ # (Asia/Brunei)
+BORT 28800 # Borneo Time (Indonesia) (not in zic)
+BTT 21600 # Bhutan Time
+ # (Asia/Thimphu)
+CCT 28800 # China Coastal Time (not in zic)
+GEST 14400 D # Georgia Summer Time (there was a timezone change in 2004)
+ # (Asia/Tbilisi)
+GET 10800 # Georgia Time (there was a timezone change in 2004)
+ # (Asia/Tbilisi)
+HKT 28800 # Hong Kong Time (not in zic)
+ICT 25200 # Indochina Time
+ # (Asia/Bangkok)
+ # (Asia/Phnom_Penh)
+ # (Asia/Saigon)
+ # (Asia/Vientiane)
+IRKST 32400 D # Irkutsk Summer Time
+ # (Asia/Irkutsk)
+IRKT 28800 # Irkutsk Time
+ # (Asia/Irkutsk)
+IRT 12600 # Iran Time (not in zic)
+# CONFLICT! IST is not unique
+# Other timezones:
+# - IST: Irish Summer Time (Europe)
+# - IST: Indian Standard Time (Asia)
+IST 7200 # Israel Standard Time (not in zic)
+JAYT 32400 # Jayapura Time (Indonesia) (not in zic)
+KDT 36000 D # Korean Daylight Time (not in zic)
+KGST 21600 D # Kyrgyzstan Summer Time
+ # (Asia/Bishkek)
+KGT 18000 # Kyrgyzstan Time
+ # (Asia/Bishkek)
+KRAST 28800 D # Krasnoyarsk Summer Time
+ # (Asia/Krasnoyarsk)
+KRAT 25200 # Krasnoyarsk Time
+ # (Asia/Krasnoyarsk)
+KST 32400 # Korean Standard Time
+ # (Asia/Pyongyang)
+LKT 21600 # Lanka Time
+ # (Asia/Colombo)
+MAGST 43200 D # Magadan Summer Time
+ # (Asia/Magadan)
+MAGT 39600 # Magadan Time
+ # (Asia/Magadan)
+MMT 23400 # Myanmar Time
+ # (Asia/Rangoon)
+MYT 28800 # Malaysia Time
+ # (Asia/Kuala_Lumpur)
+ # (Asia/Kuching)
+NOVST 25200 D # Novosibirsk Summer Time
+ # (Asia/Novosibirsk)
+NOVT 21600 # Novosibirsk Time
+ # (Asia/Novosibirsk)
+NPT 20700 # Nepal Time
+ # (Asia/Katmandu)
+OMSST 25200 D # Omsk Summer Time
+ # (Asia/Omsk)
+OMST 21600 # Omsk Time
+ # (Asia/Omsk)
+PETST 46800 D # Petropavlovsk-Kamchatski Summer Time
+ # (Asia/Kamchatka)
+PETT 43200 # Petropavlovsk-Kamchatski Time
+ # (Asia/Kamchatka)
+PHT 28800 # Phillipine Time (not in zic)
+PKT 18000 # Pakistan Time (not in zic)
+TJT 18000 # Tajikistan Time
+ # (Asia/Dushanbe)
+TMT 18000 # Turkmenistan Time
+ # (Asia/Ashgabat)
+ULAST 32400 D # Ulan Bator Summer Time
+ # (Asia/Ulaanbaatar)
+ULAT 28800 # Ulan Bator Time
+ # (Asia/Ulaanbaatar)
+UZST 21600 D # Uzbekistan Summer Time
+ # (Asia/Samarkand)
+ # (Asia/Tashkent)
+UZT 18000 # Uzbekistan Time
+ # (Asia/Samarkand)
+ # (Asia/Tashkent)
+VLAST 39600 D # Vladivostok Summer Time
+ # (Asia/Vladivostok)
+VLAT 36000 # Vladivostok Time
+ # (Asia/Vladivostok)
+YAKST 36000 D # Yakutsk Summer Time
+ # (Asia/Yakutsk)
+YAKT 32400 # Yakutsk Time
+ # (Asia/Yakutsk)
+YEKST 21600 D # Yekaterinburg Summer Time
+ # (Asia/Yekaterinburg)
+YEKT 18000 # Yekaterinburg Time
+ # (Asia/Yekaterinburg)
+
+#################### ATLANTIC ####################
+
+# CONFLICT! ADT is not unique
+# Other timezones:
+# - ADT: Arabic Daylight Time (Asia)
+ADT -10800 D # Atlantic Daylight Time
+ # (America/Glace_Bay)
+ # (America/Goose_Bay)
+ # (America/Halifax)
+ # (America/Thule)
+ # (Atlantic/Bermuda)
+# CONFLICT! AST is not unique
+# Other timezones:
+# - AST: Arabic Standard Time (Asia)
+# - AST: Al Manamah Standard Time (Asia) same offset as Arabia Standard Time
+# - AST/ACT: Acre Standard Time (America) listed as ACT
+# - AST: Anguilla Standard Time (America) same offset
+# - AST: Antigua Standard Time (America) same offset
+# - AST: Antilles Standard Time (America) same offset
+AST -14400 # Atlantic Standard Time
+ # (America/Anguilla)
+ # (America/Antigua)
+ # (America/Aruba)
+ # (America/Curacao)
+ # (America/Dominica)
+ # (America/Glace_Bay)
+ # (America/Goose_Bay)
+ # (America/Grenada)
+ # (America/Guadeloupe)
+ # (America/Halifax)
+ # (America/Martinique)
+ # (America/Montserrat)
+ # (America/Port_of_Spain)
+ # (America/Puerto_Rico)
+ # (America/Santo_Domingo)
+ # (America/St_Kitts)
+ # (America/St_Lucia)
+ # (America/St_Thomas)
+ # (America/St_Vincent)
+ # (America/Thule)
+ # (America/Tortola)
+ # (Atlantic/Bermuda)
+AZOST 0 D # Azores Summer Time
+ # (Atlantic/Azores)
+AZOT -3600 # Azores Time
+ # (Atlantic/Azores)
+FKST -10800 D # Falkland Islands Summer Time
+ # (Atlantic/Stanley)
+FKT -14400 # Falkland Islands Time
+ # (Atlantic/Stanley)
+
+#################### AUSTRALIA ####################
+
+ACSST 37800 D # Central Australia (not in zic)
+AESST 39600 D # Australia Eastern Summer Standard Time (not in zic)
+AEST 36000 # Australia Eastern Standard Time (not in zic)
+AWSST 32400 D # Australia Western Summer Standard Time (not in zic)
+AWST 28800 # Australia Western Standard Time (not in zic)
+CADT 37800 D # Central Australia Daylight-Saving Time (not in zic)
+CAST 34200 # Central Australia Standard Time (not in zic)
+LHDT 39600 D # Lord Howe Daylight Time, Australia (not in zic)
+LHST 37800 # Lord Howe Standard Time (Australia)
+ # (Australia/Lord_Howe)
+LIGT 36000 # Melbourne, Australia (not in zic)
+NZT 43200 # New Zealand Time (not in zic)
+SADT 37800 D # South Australian Daylight-Saving Time (not in zic)
+SAST 34200 # South Australian Standard Time (not in zic)
+WADT 28800 D # West Australian Daylight-Saving Time (not in zic)
+WAST 25200 # West Australian Standard Time (not in zic)
+WDT 32400 D # West Australian Daylight-Saving Time (not in zic)
+
+#################### ETC ####################
+
+GMT 0 # Greenwich Mean Time
+ # (Africa/Abidjan)
+ # (Africa/Bamako)
+ # (Africa/Banjul)
+ # (Africa/Bissau)
+ # (Africa/Conakry)
+ # (Africa/Dakar)
+ # (Africa/Lome)
+ # (Africa/Monrovia)
+ # (Africa/Nouakchott)
+ # (Africa/Ouagadougou)
+ # (Africa/Sao_Tome)
+ # (America/Danmarkshavn)
+ # (Atlantic/Reykjavik)
+ # (Atlantic/St_Helena)
+ # (Etc/GMT)
+ # (Europe/Dublin)
+ # (Europe/London)
+UCT 0 # Universal Coordinated Time
+ # (Etc/UCT)
+UT 0 # Universal Time (not in zic)
+UTC 0 # Coordinated Universal Time
+Z 0 # Zulu
+ZULU 0 # Zulu
+
+#################### EUROPE ####################
+
+BST 3600 D # British Summer Time
+ # Brazil Standard Time
+ # Bering Summer Time
+ # (Europe/London)
+BDST 7200 D # British Double Summer Time
+CEST 7200 D # Central Europe Summer Time
+ # (Africa/Ceuta)
+ # (Europe/Amsterdam)
+ # (Europe/Andorra)
+ # (Europe/Belgrade)
+ # (Europe/Berlin)
+ # (Europe/Brussels)
+ # (Europe/Budapest)
+ # (Europe/Copenhagen)
+ # (Europe/Gibraltar)
+ # (Europe/Luxembourg)
+ # (Europe/Madrid)
+ # (Europe/Malta)
+ # (Europe/Monaco)
+ # (Europe/Oslo)
+ # (Europe/Paris)
+ # (Europe/Prague)
+ # (Europe/Rome)
+ # (Europe/Stockholm)
+ # (Europe/Tirane)
+ # (Europe/Vaduz)
+ # (Europe/Vienna)
+ # (Europe/Warsaw)
+ # (Europe/Zurich)
+CET 3600 # Central Europe Time
+ # (Africa/Algiers)
+ # (Africa/Ceuta)
+ # (Europe/Amsterdam)
+ # (Europe/Andorra)
+ # (Europe/Belgrade)
+ # (Europe/Berlin)
+ # (Europe/Brussels)
+ # (Europe/Budapest)
+ # (Europe/Copenhagen)
+ # (Europe/Gibraltar)
+ # (Europe/Luxembourg)
+ # (Europe/Madrid)
+ # (Europe/Malta)
+ # (Europe/Monaco)
+ # (Europe/Oslo)
+ # (Europe/Paris)
+ # (Europe/Prague)
+ # (Europe/Rome)
+ # (Europe/Stockholm)
+ # (Europe/Tirane)
+ # (Europe/Vaduz)
+ # (Europe/Vienna)
+ # (Europe/Warsaw)
+ # (Europe/Zurich)
+CETDST 7200 D # Central Europe Summer Time
+ # (Africa/Ceuta)
+ # (Europe/Amsterdam)
+ # (Europe/Andorra)
+ # (Europe/Belgrade)
+ # (Europe/Berlin)
+ # (Europe/Brussels)
+ # (Europe/Budapest)
+ # (Europe/Copenhagen)
+ # (Europe/Gibraltar)
+ # (Europe/Luxembourg)
+ # (Europe/Madrid)
+ # (Europe/Malta)
+ # (Europe/Monaco)
+ # (Europe/Oslo)
+ # (Europe/Paris)
+ # (Europe/Prague)
+ # (Europe/Rome)
+ # (Europe/Stockholm)
+ # (Europe/Tirane)
+ # (Europe/Vaduz)
+ # (Europe/Vienna)
+ # (Europe/Warsaw)
+ # (Europe/Zurich)
+EEST 10800 D # East-Egypt Summertime
+ # Eastern Europe Summer Time
+ # (Africa/Cairo)
+ # (Asia/Amman)
+ # (Asia/Beirut)
+ # (Asia/Damascus)
+ # (Asia/Gaza)
+ # (Asia/Nicosia)
+ # (Europe/Athens)
+ # (Europe/Bucharest)
+ # (Europe/Chisinau)
+ # (Europe/Helsinki)
+ # (Europe/Istanbul)
+ # (Europe/Kaliningrad)
+ # (Europe/Kiev)
+ # (Europe/Minsk)
+ # (Europe/Riga)
+ # (Europe/Simferopol)
+ # (Europe/Sofia)
+ # (Europe/Tallinn)
+ # (Europe/Uzhgorod)
+ # (Europe/Vilnius)
+ # (Europe/Zaporozhye)
+EET 7200 # East-Egypt Time
+ # Eastern Europe Time
+ # (Africa/Cairo)
+ # (Africa/Tripoli)
+ # (Asia/Amman)
+ # (Asia/Beirut)
+ # (Asia/Damascus)
+ # (Asia/Gaza)
+ # (Asia/Nicosia)
+ # (Europe/Athens)
+ # (Europe/Bucharest)
+ # (Europe/Chisinau)
+ # (Europe/Helsinki)
+ # (Europe/Istanbul)
+ # (Europe/Kaliningrad)
+ # (Europe/Kiev)
+ # (Europe/Minsk)
+ # (Europe/Riga)
+ # (Europe/Simferopol)
+ # (Europe/Sofia)
+ # (Europe/Tallinn)
+ # (Europe/Uzhgorod)
+ # (Europe/Vilnius)
+ # (Europe/Zaporozhye)
+EETDST 10800 D # East-Egypt Summertime
+ # Eastern Europe Summer Time
+ # (Africa/Cairo)
+ # (Asia/Amman)
+ # (Asia/Beirut)
+ # (Asia/Damascus)
+ # (Asia/Gaza)
+ # (Asia/Nicosia)
+ # (Europe/Athens)
+ # (Europe/Bucharest)
+ # (Europe/Chisinau)
+ # (Europe/Helsinki)
+ # (Europe/Istanbul)
+ # (Europe/Kaliningrad)
+ # (Europe/Kiev)
+ # (Europe/Minsk)
+ # (Europe/Riga)
+ # (Europe/Simferopol)
+ # (Europe/Sofia)
+ # (Europe/Tallinn)
+ # (Europe/Uzhgorod)
+ # (Europe/Vilnius)
+ # (Europe/Zaporozhye)
+MEST 7200 D # Middle Europe Summer Time (not in zic)
+MET 3600 # Middle Europe Time (not in zic)
+METDST 7200 D # Middle Europe Summer Time (not in zic)
+MEZ 3600 # Mitteleuropaeische Zeit (German) (not in zic)
+MSD 14400 D # Moscow Daylight Time
+ # (Europe/Moscow)
+MSK 10800 # Moscow Time
+ # (Europe/Moscow)
+WET 0 # Western Europe Time
+ # (Africa/Casablanca)
+ # (Africa/El_Aaiun)
+ # (Atlantic/Canary)
+ # (Atlantic/Faeroe)
+ # (Atlantic/Madeira)
+ # (Europe/Lisbon)
+WETDST 3600 D # Western Europe Summer Time
+ # (Atlantic/Canary)
+ # (Atlantic/Faeroe)
+ # (Atlantic/Madeira)
+ # (Europe/Lisbon)
+
+#################### INDIAN ####################
+
+CXT 25200 # Christmas Island Time (Indian Ocean)
+ # (Indian/Christmas)
+IOT 21600 # British Indian Ocean Territory (Chagos) (there was a timezone change recently in 1996)
+ # (Indian/Chagos)
+MUT 14400 # Mauritius Island Time
+ # (Indian/Mauritius)
+MVT 18000 # Maldives Island Time
+ # (Indian/Maldives)
+RET 14400 # Reunion Time
+ # (Indian/Reunion)
+SCT 14400 # Seychelles Time
+ # (Indian/Mahe)
+TFT 18000 # Kerguelen Time
+ # (Indian/Kerguelen)
+
+#################### PACIFIC ####################
+
+CHADT 49500 D # Chatham Daylight Time (New Zealand)
+ # (Pacific/Chatham)
+CHAST 45900 # Chatham Standard Time (New Zealand)
+ # (Pacific/Chatham)
+CKT 43200 # Cook Islands Time (not in zic)
+EASST -18000 D # Easter Island Summer Time (Chile)
+ # (Pacific/Easter)
+EAST -21600 # Easter Island Time (Chile)
+ # (Pacific/Easter)
+FJST -46800 D # Fiji Summer Time (not in zic)
+FJT -43200 # Fiji Time (not in zic)
+GALT -21600 # Galapagos Time
+ # (Pacific/Galapagos)
+GAMT -32400 # Gambier Time
+ # (Pacific/Gambier)
+GILT 43200 # Gilbert Islands Time
+ # (Pacific/Tarawa)
+HST -36000 # Hawaiian Standard Time
+ # (Pacific/Honolulu)
+ # (Pacific/Johnston)
+KOST 39600 # Kosrae Time
+ # (Pacific/Kosrae)
+LINT 50400 # Line Islands Time (Kiribati)
+ # (Pacific/Kiritimati)
+MART -34200 # Marquesas Time
+ # (Pacific/Marquesas)
+MHT 43200 # Kwajalein Time
+ # (Pacific/Kwajalein)
+ # (Pacific/Majuro)
+MPT 36000 # North Mariana Islands Time (not in zic)
+# CONFLICT! NFT is not unique
+# Other timezones:
+# - NFT: Norfolk Time (Pacific)
+NFT -12600 # Newfoundland Time (not in zic)
+NUT -39600 # Niue Time
+ # (Pacific/Niue)
+NZDT 46800 D # New Zealand Daylight Time
+ # (Antarctica/McMurdo)
+ # (Pacific/Auckland)
+NZST 43200 # New Zealand Standard Time
+ # (Antarctica/McMurdo)
+ # (Pacific/Auckland)
+PGT 36000 # Papua New Guinea Time
+ # (Pacific/Port_Moresby)
+PHOT 46800 # Phoenix Islands Time (Kiribati)
+ # (Pacific/Enderbury)
+PONT 39600 # Ponape Time (Micronesia)
+ # (Pacific/Ponape)
+PWT 32400 # Palau Time
+ # (Pacific/Palau)
+TAHT -36000 # Tahiti Time (zic says "TAHT", other sources "THAT")
+ # (Pacific/Tahiti)
+TKT -36000 # Tokelau Time
+ # (Pacific/Fakaofo)
+TOT 46800 # Tonga Time (not in zic)
+TRUT 36000 # Truk Time (zic says "TRUT", other souces say "TRUK")
+ # (Pacific/Truk)
+TVT 43200 # Tuvalu Time
+ # (Pacific/Funafuti)
+VUT 39600 # Vanuata Time (not in zic)
+WAKT 43200 # Wake Time
+ # (Pacific/Wake)
+WFT 43200 # Wallis and Futuna Time
+ # (Pacific/Wallis)
+YAPT 36000 # Yap Time (Micronesia) (not in zic)
+
diff --git a/src/timezone/tznames/Etc.txt b/src/timezone/tznames/Etc.txt
new file mode 100644
index 00000000000..9d8d15f055b
--- /dev/null
+++ b/src/timezone/tznames/Etc.txt
@@ -0,0 +1,33 @@
+#
+# NOTE:
+# This file is NOT loaded by the PostgreSQL database. It just serves as
+# a template for timezones you could need. See the `Date/Time Support'
+# appendix in the PostgreSQL documentation for more information.
+#
+
+GMT 0 # Greenwich Mean Time
+ # (Africa/Abidjan)
+ # (Africa/Bamako)
+ # (Africa/Banjul)
+ # (Africa/Bissau)
+ # (Africa/Conakry)
+ # (Africa/Dakar)
+ # (Africa/Lome)
+ # (Africa/Monrovia)
+ # (Africa/Nouakchott)
+ # (Africa/Ouagadougou)
+ # (Africa/Sao_Tome)
+ # (America/Danmarkshavn)
+ # (Atlantic/Reykjavik)
+ # (Atlantic/St_Helena)
+ # (Etc/GMT)
+ # (Europe/Dublin)
+ # (Europe/London)
+UCT 0 # Universal Coordinated Time
+ # (Etc/UCT)
+UT 0 # Universal Time (not in zic)
+UTC 0 # Coordinated Universal Time
+ # (Etc/UTC)
+Z 0 # Zulu
+ZULU 0 # Zulu
+
diff --git a/src/timezone/tznames/Europe.txt b/src/timezone/tznames/Europe.txt
new file mode 100644
index 00000000000..19839a69a01
--- /dev/null
+++ b/src/timezone/tznames/Europe.txt
@@ -0,0 +1,207 @@
+#
+# NOTE:
+# This file is NOT loaded by the PostgreSQL database. It just serves as
+# a template for timezones you could need. See the `Date/Time Support'
+# appendix in the PostgreSQL documentation for more information.
+#
+
+BST 3600 D # British Summer Time
+ # Brazil Standard Time
+ # Bering Summer Time
+ # (Europe/London)
+CEST 7200 D # Central Europe Summer Time
+ # (Africa/Ceuta)
+ # (Europe/Amsterdam)
+ # (Europe/Andorra)
+ # (Europe/Belgrade)
+ # (Europe/Berlin)
+ # (Europe/Brussels)
+ # (Europe/Budapest)
+ # (Europe/Copenhagen)
+ # (Europe/Gibraltar)
+ # (Europe/Luxembourg)
+ # (Europe/Madrid)
+ # (Europe/Malta)
+ # (Europe/Monaco)
+ # (Europe/Oslo)
+ # (Europe/Paris)
+ # (Europe/Prague)
+ # (Europe/Rome)
+ # (Europe/Stockholm)
+ # (Europe/Tirane)
+ # (Europe/Vaduz)
+ # (Europe/Vienna)
+ # (Europe/Warsaw)
+ # (Europe/Zurich)
+CET 3600 # Central Europe Time
+ # (Africa/Algiers)
+ # (Africa/Ceuta)
+ # (Europe/Amsterdam)
+ # (Europe/Andorra)
+ # (Europe/Belgrade)
+ # (Europe/Berlin)
+ # (Europe/Brussels)
+ # (Europe/Budapest)
+ # (Europe/Copenhagen)
+ # (Europe/Gibraltar)
+ # (Europe/Luxembourg)
+ # (Europe/Madrid)
+ # (Europe/Malta)
+ # (Europe/Monaco)
+ # (Europe/Oslo)
+ # (Europe/Paris)
+ # (Europe/Prague)
+ # (Europe/Rome)
+ # (Europe/Stockholm)
+ # (Europe/Tirane)
+ # (Europe/Vaduz)
+ # (Europe/Vienna)
+ # (Europe/Warsaw)
+ # (Europe/Zurich)
+CETDST 7200 D # Central Europe Summer Time
+ # (Africa/Ceuta)
+ # (Europe/Amsterdam)
+ # (Europe/Andorra)
+ # (Europe/Belgrade)
+ # (Europe/Berlin)
+ # (Europe/Brussels)
+ # (Europe/Budapest)
+ # (Europe/Copenhagen)
+ # (Europe/Gibraltar)
+ # (Europe/Luxembourg)
+ # (Europe/Madrid)
+ # (Europe/Malta)
+ # (Europe/Monaco)
+ # (Europe/Oslo)
+ # (Europe/Paris)
+ # (Europe/Prague)
+ # (Europe/Rome)
+ # (Europe/Stockholm)
+ # (Europe/Tirane)
+ # (Europe/Vaduz)
+ # (Europe/Vienna)
+ # (Europe/Warsaw)
+ # (Europe/Zurich)
+EEST 10800 D # East-Egypt Summertime
+ # Eastern Europe Summer Time
+ # (Africa/Cairo)
+ # (Asia/Amman)
+ # (Asia/Beirut)
+ # (Asia/Damascus)
+ # (Asia/Gaza)
+ # (Asia/Nicosia)
+ # (Europe/Athens)
+ # (Europe/Bucharest)
+ # (Europe/Chisinau)
+ # (Europe/Helsinki)
+ # (Europe/Istanbul)
+ # (Europe/Kaliningrad)
+ # (Europe/Kiev)
+ # (Europe/Minsk)
+ # (Europe/Riga)
+ # (Europe/Simferopol)
+ # (Europe/Sofia)
+ # (Europe/Tallinn)
+ # (Europe/Uzhgorod)
+ # (Europe/Vilnius)
+ # (Europe/Zaporozhye)
+EET 7200 # East-Egypt Time
+ # Eastern Europe Time
+ # (Africa/Cairo)
+ # (Africa/Tripoli)
+ # (Asia/Amman)
+ # (Asia/Beirut)
+ # (Asia/Damascus)
+ # (Asia/Gaza)
+ # (Asia/Nicosia)
+ # (Europe/Athens)
+ # (Europe/Bucharest)
+ # (Europe/Chisinau)
+ # (Europe/Helsinki)
+ # (Europe/Istanbul)
+ # (Europe/Kaliningrad)
+ # (Europe/Kiev)
+ # (Europe/Minsk)
+ # (Europe/Riga)
+ # (Europe/Simferopol)
+ # (Europe/Sofia)
+ # (Europe/Tallinn)
+ # (Europe/Uzhgorod)
+ # (Europe/Vilnius)
+ # (Europe/Zaporozhye)
+EETDST 10800 D # East-Egypt Summertime
+ # Eastern Europe Summer Time
+ # (Africa/Cairo)
+ # (Asia/Amman)
+ # (Asia/Beirut)
+ # (Asia/Damascus)
+ # (Asia/Gaza)
+ # (Asia/Nicosia)
+ # (Europe/Athens)
+ # (Europe/Bucharest)
+ # (Europe/Chisinau)
+ # (Europe/Helsinki)
+ # (Europe/Istanbul)
+ # (Europe/Kaliningrad)
+ # (Europe/Kiev)
+ # (Europe/Minsk)
+ # (Europe/Riga)
+ # (Europe/Simferopol)
+ # (Europe/Sofia)
+ # (Europe/Tallinn)
+ # (Europe/Uzhgorod)
+ # (Europe/Vilnius)
+ # (Europe/Zaporozhye)
+GMT 0 # Greenwich Mean Time
+ # (Africa/Abidjan)
+ # (Africa/Bamako)
+ # (Africa/Banjul)
+ # (Africa/Bissau)
+ # (Africa/Conakry)
+ # (Africa/Dakar)
+ # (Africa/Lome)
+ # (Africa/Monrovia)
+ # (Africa/Nouakchott)
+ # (Africa/Ouagadougou)
+ # (Africa/Sao_Tome)
+ # (America/Danmarkshavn)
+ # (Atlantic/Reykjavik)
+ # (Atlantic/St_Helena)
+ # (Etc/GMT)
+ # (Europe/Dublin)
+ # (Europe/London)
+# CONFLICT! IST is not unique
+# Other timezones:
+# - IST: Indian Standard Time (Asia)
+# - IST: Israel Standard Time (Asia)
+IST 3600 D # Irish Summer Time
+ # (Europe/Dublin)
+MEST 7200 D # Middle Europe Summer Time (not in zic)
+MET 3600 # Middle Europe Time (not in zic)
+METDST 7200 D # Middle Europe Summer Time (not in zic)
+MEZ 3600 # Mitteleuropäische Zeit (German) (not in zic)
+MSD 14400 D # Moscow Daylight Time
+ # (Europe/Moscow)
+MSK 10800 # Moscow Time
+ # (Europe/Moscow)
+SAMST 18000 D # Samara Summer Time
+ # (Europe/Samara)
+SAMT 14400 # Samara Time
+ # (Europe/Samara)
+WEST 3600 D # Western Europe Summer Time
+ # (Atlantic/Canary)
+ # (Atlantic/Faeroe)
+ # (Atlantic/Madeira)
+ # (Europe/Lisbon)
+WET 0 # Western Europe Time
+ # (Africa/Casablanca)
+ # (Africa/El_Aaiun)
+ # (Atlantic/Canary)
+ # (Atlantic/Faeroe)
+ # (Atlantic/Madeira)
+ # (Europe/Lisbon)
+WETDST 3600 D # Western Europe Summer Time
+ # (Atlantic/Canary)
+ # (Atlantic/Faeroe)
+ # (Atlantic/Madeira)
+ # (Europe/Lisbon)
diff --git a/src/timezone/tznames/India b/src/timezone/tznames/India
new file mode 100644
index 00000000000..11e4d126093
--- /dev/null
+++ b/src/timezone/tznames/India
@@ -0,0 +1,12 @@
+# Time zone configuration file for set "India"
+
+# In order to use this file, you need to set the run-time parameter
+# timezone_abbreviations to 'India'. See the `Date/Time Support'
+# appendix in the PostgreSQL documentation for more information.
+
+
+# include the default set
+@INCLUDE Default
+
+IST 19800 # Indian Standard Time
+ # (Asia/Calcutta)
diff --git a/src/timezone/tznames/Indian.txt b/src/timezone/tznames/Indian.txt
new file mode 100644
index 00000000000..06a880ecc98
--- /dev/null
+++ b/src/timezone/tznames/Indian.txt
@@ -0,0 +1,35 @@
+#
+# NOTE:
+# This file is NOT loaded by the PostgreSQL database. It just serves as
+# a template for timezones you could need. See the `Date/Time Support'
+# appendix in the PostgreSQL documentation for more information.
+#
+
+CCT 23400 # Cocos Islands Time (Indian Ocean)
+ # (Indian/Cocos)
+CXT 25200 # Christmas Island Time (Indian Ocean)
+ # (Indian/Christmas)
+EAT 10800 # East Africa Time
+ # (Africa/Addis_Ababa)
+ # (Africa/Asmera)
+ # (Africa/Dar_es_Salaam)
+ # (Africa/Djibouti)
+ # (Africa/Kampala)
+ # (Africa/Khartoum)
+ # (Africa/Mogadishu)
+ # (Africa/Nairobi)
+ # (Indian/Antananarivo)
+ # (Indian/Comoro)
+ # (Indian/Mayotte)
+IOT 21600 # British Indian Ocean Territory (Chagos) (there was a timezone change recently in 1996)
+ # (Indian/Chagos)
+MUT 14400 # Mauritius Island Time
+ # (Indian/Mauritius)
+MVT 18000 # Maldives Island Time
+ # (Indian/Maldives)
+RET 14400 # Reunion Time
+ # (Indian/Reunion)
+SCT 14400 # Seychelles Time
+ # (Indian/Mahe)
+TFT 18000 # Kerguelen Time
+ # (Indian/Kerguelen)
diff --git a/src/timezone/tznames/Makefile b/src/timezone/tznames/Makefile
new file mode 100644
index 00000000000..aca2c595963
--- /dev/null
+++ b/src/timezone/tznames/Makefile
@@ -0,0 +1,30 @@
+#-------------------------------------------------------------------------
+#
+# Makefile
+# Makefile for the timezone names
+
+# IDENTIFICATION
+# $PostgreSQL: pgsql/src/timezone/tznames/Makefile,v 1.1 2006/07/25 03:51:23 tgl Exp $
+#
+#-------------------------------------------------------------------------
+
+subdir = src/timezone/tznames
+top_builddir = ../../..
+include $(top_builddir)/src/Makefile.global
+
+TZNAMES_TEMPLATES := Africa.txt America.txt Antarctica.txt Asia.txt \
+ Atlantic.txt Australia.txt Etc.txt Europe.txt Indian.txt Pacific.txt
+TZNAMES_TEMPLATES_FILES := $(TZNAMES_TEMPLATES:%=$(srcdir)/%)
+
+TZNAMES_SETS := Default Australia India
+TZNAMES_SETS_FILES := $(TZNAMES_SETS:%=$(srcdir)/%)
+
+install: installdirs
+ $(INSTALL_DATA) $(TZNAMES_TEMPLATES_FILES) '$(DESTDIR)$(datadir)/timezonesets'
+ $(INSTALL_DATA) $(TZNAMES_SETS_FILES) '$(DESTDIR)$(datadir)/timezonesets'
+
+installdirs:
+ $(mkinstalldirs) '$(DESTDIR)$(datadir)/timezonesets'
+
+uninstall:
+ rm -rf '$(DESTDIR)$(datadir)/timezonesets'
diff --git a/src/timezone/tznames/Pacific.txt b/src/timezone/tznames/Pacific.txt
new file mode 100644
index 00000000000..1616b939f79
--- /dev/null
+++ b/src/timezone/tznames/Pacific.txt
@@ -0,0 +1,100 @@
+#
+# NOTE:
+# This file is NOT loaded by the PostgreSQL database. It just serves as
+# a template for timezones you could need. See the `Date/Time Support'
+# appendix in the PostgreSQL documentation for more information.
+#
+
+CHADT 49500 D # Chatham Daylight Time (New Zealand)
+ # (Pacific/Chatham)
+CHAST 45900 # Chatham Standard Time (New Zealand)
+ # (Pacific/Chatham)
+ChST 36000 # Chamorro Standard Time (lower case "h" is as in zic)
+ # (Pacific/Guam)
+ # (Pacific/Saipan)
+CKT 43200 # Cook Islands Time (not in zic)
+EASST -18000 D # Easter Island Summer Time (Chile)
+ # (Pacific/Easter)
+# CONFLICT! EAST is not unique
+# Other timezones:
+# - EAST: East Australian Standard Time (Australia)
+EAST -21600 # Easter Island Time (Chile)
+ # (Pacific/Easter)
+FJST -46800 D # Fiji Summer Time (not in zic)
+FJT -43200 # Fiji Time (not in zic)
+GALT -21600 # Galapagos Time
+ # (Pacific/Galapagos)
+GAMT -32400 # Gambier Time
+ # (Pacific/Gambier)
+GILT 43200 # Gilbert Islands Time
+ # (Pacific/Tarawa)
+HST -36000 # Hawaiian Standard Time
+ # (Pacific/Honolulu)
+ # (Pacific/Johnston)
+KOST 39600 # Kosrae Time
+ # (Pacific/Kosrae)
+LINT 50400 # Line Islands Time (Kiribati)
+ # (Pacific/Kiritimati)
+MART -34200 # Marquesas Time
+ # (Pacific/Marquesas)
+MHT 43200 # Kwajalein Time
+ # (Pacific/Kwajalein)
+ # (Pacific/Majuro)
+MPT 36000 # North Mariana Islands Time (not in zic)
+NCT 39600 # New Caledonia Time (not in zic)
+# CONFLICT! NFT is not unique
+# Other timezones:
+# - NFT: Newfoundland Time (America)
+NFT 41400 # Norfolk Time
+ # (Pacific/Norfolk)
+NRT 43200 # Nauru Time
+ # (Pacific/Nauru)
+NUT -39600 # Niue Time
+ # (Pacific/Niue)
+NZDT 46800 D # New Zealand Daylight Time
+ # (Antarctica/McMurdo)
+ # (Pacific/Auckland)
+NZST 43200 # New Zealand Standard Time
+ # (Antarctica/McMurdo)
+ # (Pacific/Auckland)
+PGT 36000 # Papua New Guinea Time
+ # (Pacific/Port_Moresby)
+PHOT 46800 # Phoenix Islands Time (Kiribati)
+ # (Pacific/Enderbury)
+PONT 39600 # Ponape Time (Micronesia)
+ # (Pacific/Ponape)
+PST -28800 # Pacific Standard Time
+ # (America/Dawson)
+ # (America/Los_Angeles)
+ # (America/Tijuana)
+ # (America/Vancouver)
+ # (America/Whitehorse)
+ # (Pacific/Pitcairn)
+PWT 32400 # Palau Time
+ # (Pacific/Palau)
+SBT 39600 # Solomon Islands Time
+ # (Pacific/Guadalcanal)
+SST -39600 # South Sumatran Time
+ # (Pacific/Midway)
+ # (Pacific/Pago_Pago)
+TAHT -36000 # Tahiti Time (zic says "TAHT", other sources "THAT")
+ # (Pacific/Tahiti)
+TKT -36000 # Tokelau Time
+ # (Pacific/Fakaofo)
+TOT 46800 # Tonga Time (not in zic)
+TRUT 36000 # Truk Time (zic says "TRUT", other souces say "TRUK")
+ # (Pacific/Truk)
+TVT 43200 # Tuvalu Time
+ # (Pacific/Funafuti)
+VUT 39600 # Vanuata Time (not in zic)
+WAKT 43200 # Wake Time
+ # (Pacific/Wake)
+WFT 43200 # Wallis and Futuna Time
+ # (Pacific/Wallis)
+# CONFLICT! WST is not unique
+# Other timezones:
+# - WST: Western Standard Time (Australia)
+WST -39600 # West Samoa Time
+ # (Pacific/Apia)
+YAPT 36000 # Yap Time (Micronesia) (not in zic)
+
diff --git a/src/timezone/tznames/README b/src/timezone/tznames/README
new file mode 100644
index 00000000000..ce4538873e2
--- /dev/null
+++ b/src/timezone/tznames/README
@@ -0,0 +1,18 @@
+This directory contains files with timezone sets for PostgreSQL. The problem
+is that time zone abbreviations are not unique throughout the world and you
+might find out that a time zone abbreviation in the `Default' set collides
+with the one you wanted to use. All other files except for `Default' are
+intended to override values from the `Default' set. So you might already have
+a file here that serves your needs. If not, you can create your own.
+
+In order to use one of these files, you need to set
+
+ timezone_abbreviations = 'xyz'
+
+in any of the usual ways for setting a parameter, where xyz is the filename
+that contains the desired time zone names.
+
+If you do not find an appropriate set of time zone names for your geographic
+location supplied here, please report this to .
+Your set of time zone names can then be included in future releases.
+For the time being you can always add your own set.