Appendix A. 日期/时间支持

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

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

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

A.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. 如果超过4位数字,而且前面也没有读到其它日期字段, 那么就解释成一个"连接的日期"(比如,19990118)。 8和6位分别解释成年,月,和日,而7和5位分别解释成年,年日。

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

    3. 如果已经读取了四和六位数字,并且已经读取了一个年份, 那么就解释成时间。

    4. 如果是四或更多位,则解析成一个年份。

    5. 如果是欧洲日期模式,并且还未读取到日期字段,并且数值小于或等于31, 那么解析成某一天。

    6. 如果还未读取月份字段,并且数值小于或等于12,那么解析成月份。

    7. 如果日期域尚未读取,并且数值小于或等于31,则解析成一天。

    8. 如果是两位或者四或更多位数字,那么解析成一年。

    9. 否则,抛出一个错误。

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

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

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