因为目前还没有标准的 *nix 系统接口可以用于访问通用的跨时区的时区信息, 所以 PostgreSQL 包含一个内部的小表用以时区解码。 不过,下层的 OS 的确提供了输出 时区信息。
下面这个 PostgreSQL 能够识别的 时区表是以它们相对 UTC 的时区偏移量来组织的,而不是按照字母顺序; 我们的目的是能实现匹配那些区域中有这些缩写的区域用户, 以免这些缩写混淆.
Table A-4. PostgreSQL 能识别的时区
| 时区 | 与 UTC 的偏移量 | 描述 |
|---|---|---|
| NZDT | +13:00 | 新西兰白昼时间 |
| IDLE | +12:00 | 国际日期变更线,东边 |
| NZST | +12:00 | 新西兰标准时间 |
| NZT | +12:00 | 新西兰时间 |
| AESST | +11:00 | 澳大利亚东部标准夏时制 |
| ACSST | +10:30 | 中澳大利亚标准夏时制 |
| CADT | +10:30 | 中澳大利亚夏时制 |
| SADT | +10:30 | 南澳大利亚夏时制 |
| AEST | +10:00 | 澳大利亚东部标准时间 |
| EAST | +10:00 | 东澳大利亚标准时间 |
| GST | +10:00 | 关岛标准时间,USSR Zone 9 |
| LIGT | +10:00 | 澳大利亚墨尔本 |
| CAST | +09:30 | 中澳大利亚标准时间 |
| SAST | +09:30 | 南澳大利亚标准时间 |
| CAST | +09:30 | 中澳大利亚标准时间 |
| AWSST | +09:00 | 澳大利亚西部标准夏时制 |
| JST | +09:00 | 日本标准时间,(USSR Zone 8) |
| KST | +09:00 | 韩国标准时间 |
| MHT | +09:00 | Kwajalein Time |
| WDT | +09:00 | 西澳大利亚夏时制 |
| MT | +08:30 | 毛里求斯(moluccas)时间(?) |
| AWST | +08:00 | 澳大利亚西部标准时间 |
| CCT | +08:00 | 中国沿海时间 |
| WADT | +08:00 | 西澳大利亚夏时制 |
| WST | +08:00 | 西澳大利亚标准时间 |
| JT | +07:30 | 爪哇时间 |
| ALMST | +07:00 | Almaty 夏令时 |
| WAST | +07:00 | 西澳大利亚标准时间 |
| CXT | +07:00 | Christmas (复活节?)岛时间 |
| ALMT | +06:00 | Almaty 时间 |
| MAWT | +06:00 | Mawson (Antarctica) Time |
| IOT | +05:00 | 印度 Chagos 时间 |
| MVT | +05:00 | Maldives (?)岛时间 |
| TFT | +05:00 | Kerguelen 时间 |
| AFT | +04:30 | 阿富汗时间 |
| EAST | +04:00 | Antananarivo Savings Time |
| MUT | +04:00 | Mauritius Island Time |
| RET | +04:00 | Reunion Island Time |
| SCT | +04:00 | Mahe Island Time |
| IT | +03:30 | 伊朗时间 |
| EAT | +03:00 | Antananarivo, Comoro Time |
| BT | +03:00 | 巴格达时间 |
| EETDST | +03:00 | 东欧夏时制 |
| HMT | +03:00 | Hellas Mediterranean Time (?) |
| BDST | +02:00 | British Double Standard Time |
| CEST | +02:00 | Central European Savings Time |
| CETDST | +02:00 | 中欧夏时制 |
| EET | +02:00 | 东欧,(USSR Zone 1) |
| FWT | +02:00 | 法国冬时制 |
| IST | +02:00 | 以色列标准时间 |
| MEST | +02:00 | 中欧夏时制 |
| METDST | +02:00 | 中欧白昼时间 |
| SST | +02:00 | 瑞典夏时制 |
| BST | +01:00 | 英国夏时制 |
| CET | +01:00 | 中欧时间 |
| DNT | +01:00 | Dansk Normal Tid |
| FST | +01:00 | 法国夏时制 |
| MET | +01:00 | 中欧时间 |
| MEWT | +01:00 | 中欧冬时制 |
| MEZ | +01:00 | 中欧时区 |
| NOR | +01:00 | 挪威标准时间 |
| SET | +01:00 | Seychelles Time(?) |
| SWT | +01:00 | 瑞典冬时制 |
| WETDST | +01:00 | 西欧光照利用时间(夏时制) |
| GMT | 0:00 | 格林威治标准时间 |
| UT | +00:00 | 全球时间 |
| UTC | +00:00 | 校准的全球时间 |
| Z | +00:00 | 和 UTC 相同 |
| ZULU | +00:00 | 和 UTC 相同 |
| WET | +00:00 | 西欧 |
| WAT | -01:00 | 西非时间 |
| NDT | -02:30 | 纽芬兰(Newfoundland)白昼时间 |
| ADT | -03:00 | 大西洋白昼时间 |
| AWT | -03:00 | (未知) |
| NFT | -03:30 | 纽芬兰(Newfoundland)标准时间 |
| NST | -03:30 | 纽芬兰(Newfoundland)标准时间 |
| AST | -04:00 | 大西洋标准时间(加拿大) |
| ACST | -04:00 | Atlantic/Porto Acre 夏令时 |
| ACT | -05:00 | Atlantic/Porto Acre 标准时间 |
| EDT | -04:00 | 东部白昼时间 |
| CDT | -05:00 | 中部白昼时间 |
| EST | -05:00 | 东部标准时间 |
| CST | -06:00 | 中部标准时间 |
| MDT | -06:00 | 山区白昼时间(译注:Mountain Daylight Time那位知道怎么译?) |
| MST | -07:00 | 山区标准时间 |
| PDT | -07:00 | 太平洋白昼时间 |
| AKDT | -08:00 | 阿拉斯加白昼时间 |
| PST | -08:00 | 太平洋标准时间 |
| YDT | -08:00 | Yukon 白昼时间 |
| AKST | -09:00 | 阿拉斯加标准时间 |
| HDT | -09:00 | 夏威仪/阿拉斯加白昼时间 |
| YST | -09:00 | Yukon 标准时 |
| AHST | -10:00 | 夏威夷-阿拉斯加标准时间 |
| HST | -10:00 | 夏威夷标准时间 |
| CAT | -10:00 | 中阿拉斯加时间 |
| NT | -11:00 | 州时间(Nome Time) |
| IDLW | -12:00 | 国际日期变更线,西边 |
澳大利亚时区和它的命名变体占了 PostgreSQL 时区表的整整四分之一。 有两个命名与美国使用的通用时区有冲突 CST 和 EST。
如果设置了运行时选项 USE_AUSTRALIAN_RULES,那么 CST ,EST 和 SAT 将被解释为澳大利亚时区的名字。 如果没有这个选项,CST 和 EST 将 被解释成美国时区名字,而SAT 则是 表示"Saturday(星期六)"的无用字符.
时间/日期类型都使用一套通用的过程进行翻译。
时间/日期解释
把输入字串分解成不同的记号,然后这些记号分类成字符串, 时间,时区或者数字。
如果一个数字记号包含冒号(":"),那它是时间串。
如果一个数字记号包含划线("-"),斜杠("/"),或两个或更多个点("."), 则是一个日期串,可能带有文本月份。
如果记号只有数字,那它要么是一个单一的域, 要么是一个 ISO-8601 连接的日期(例如, "19990113" 是 1999年一月十三日)或者时间(如,141516 是 14:15:16)。
如果一个记号由加号("+")或减号("-")开头, 那么它要么是一个时区,要么是特殊的域。
如果记号是一个文本字串,匹配可能的字串。
在表里面做一次对分搜索,找出记号是特殊字串(如, today), 日子(如,Thursday), 月(如,January), 或者是无关字(如,at,on)。
为数域设置数域值和位掩码。例如,为 today 设置年,月,日,以及为 now 设置额外的小时,分钟,秒钟等。
如果没有找到,对表做一次对分搜索,查找匹配记号的时区。
如果还没有找到,扔出去一个错误。
如果记号是一个数字或者数字数域。
如果多于 4 位数字,而且前面没有读取任何其他的日期域, 那么解释为一个 "联接的日期" (如, 19990118)。 8 和 6 位数被解释成年,月和日,而 7 和 5 位数分别解释成年,年日。
如果一个记号是三位数,而且一个年份已经被解码了,那么解释成年日。
如果是四或者六位,并且前面已经找到一个年份,那么解释为一个时间.
如果长于四位数,那么解释成一个年份。
如果处于欧洲日期模式,并且日期域还没有被读取, 而且数值小于或等于 31,那么解释成一天。
如果月份域还没有被读取,而且如果数值小于或等于 12, 那么解释成一个月份。
如果日期域还没有读取,而且数值小于或等于 31, 那么解释成一个日期。
如果有两位或四位或更多位数字,那么解释成一年.
否则,抛出一个错误.
如果声明了 BC,把年份数值取负值并且数值加一 用于内部存储(在罗马纪年里面没有零年,所以数字年份 1BC是公元零年)。
如果没有声明 BC,而且如果年份域有两位数长度, 那么调整年份到 4 位数。如果数据域小于 70,那么加上 2000; 否则,加 1900。
技巧: 罗马纪元 1-99AD 可以用带前导零的 4 位数进行输入 (例如,0099 是 99AD)。 早期的 PostgreSQL 接受 三位数字或者一位数字做年份,但是到了 v7.0,我们把规则定得 更严格,以减少歧义的可能.