Appendix B. 日期/时间支持

Table of Contents
B.1. 日期/时间输入解析
B.2. 日期/时间关键字
B.3. 日期单位的历史

PostgreSQL 使用一个内部的启发式分析器用于所有的日期/时间支持。 日期和时间都是以字串形式输入的,然后用一个初步的判断分解为在该数域里可以有什么样的信息。 每个数域都被解释,并且要么是被赋予一个数字值,要么是忽略, 要么是被拒绝。分析器里包含内部的查询表,用于所有文本域,包括月份,星期几,和时区。

这份附录包含这些查询表的信息,以及描述了分析器用来对时间和日期解码的步骤。

B.1. 日期/时间输入解析

日期/时间类型输入都是使用下列的过程进行解码的。

  1. 把输入字串分解为一个个记号,然后把每个记号分成字串,时间,时区,或者数字几类。

    1. 如果一个数字记号包含一个冒号(:),那么这是一个时间字串。包括随后所有的数据位和冒号。

    2. 如果这个数字记号包含一个划线(-),斜杠(/), 或者两个或多个点(.),那么它就是一个日期字串,可能有一个文本月份。

    3. 如果这个记号只是数字,那么它要么是一个单独的字段, 要么是一个 ISO 8601 连接的日期(比如,19990113 是 1999 年一月 13 日)或者是连接的时间(比如,141516 是 14:15:16)。

    4. 如果记号以一个加号(+)开头或者减号(-)开头, 那么它要么是一个时区,要么就是一个特殊的字段。

  2. 如果记号是一个文本字串,那么和可能的字串进行匹配。

    1. 做一次二分表查找,看看这个记号是特殊字串(比如,today), 日期(比如,Thursday),月份(比如,January), 还是一个无关痛痒的字(比如,aton)。

      为字段设置数值和位掩码。比如,为 today 设置年,月,日, 以及为 now 这样的还需要设置另外的时,分,秒。

    2. 如果没有找到,则做一次类似的二分表搜索,找与记号匹配的时区。

    3. 如果还没有找到,抛出一个错误。

  3. 记号是一个数字或者数字字段。

    1. 如果有八位或者六位数字,而且前面也没有读到其它日期字段, 那么就解释成一个"连接的日期"(比如, 19990118 或者 990118)。 这里的解析是 YYYYMMDD 或者 YYMMDD

    2. 如果记号是三位数字,并且已经解码了一个年份,那么解释成年日。

    3. 如果已经读取了四和六位数字,并且已经读取了一个年份, 那么就解析成时间(HHMM 或者 HHMMSS)。

    4. 如果是三位或更多位并且还没有找到日期字段,则解析成一个年份 (这个解析强制剩余的日期字段的顺序为 yy-mm-dd)。

    5. 那么解析成某一天。 否则,日期字段的顺序被认为是尊循 DateStyle 设置: mm-dd-yy,dd-mm-yy,或者 yy-mm-dd。如果发现月份或者日期字段超出范围, 则抛出一个错误。

  4. 如果声明了 BC,则对年份取其负数并加一,用于内部保存。 (在格里高利历法里没有零年,所以数字上的 1 BC 是公元零年。)

  5. 如果没有声明 BC,并且年份字段有两个数据位的长度, 那么把年份调整为 4 位。如果该字段小于 70,那么加 2000;否则,加 1900。

    提示: 格里高利年份 AD 1-99可以用前导零的方式使用4位数字 (也就是说,0099 是 AD 99)。 以前的 PostgreSQL 版本接受三位数字的年份和一位数字的年份, 但是从版本 7.0 开始,这个规则更严格了,以减少可能的混淆。