PostgreSQL 使用一个内部的启发式分析器 用于所有的日期/时间支持.日期和时间都是以字串形式输入的, 然后用一个初步的判断分解为在该数域里可以有什么样的信息. 每个数域都被解释,并且要么是被赋予一个数字值,要么是忽略, 要么是被拒绝.分析器里包含内部的查询表,用于所有文本域, 包括月份,星期几,和时区.
这份附录包含这些查询表的信息,以及描述了分析器用来对时间和日期 解码的步骤.
日期/时间类型都是使用一套通用的过程进行解析的。
日期/时间输入解析
把输入字串分解为一个个记号,然后把每个记号分成字串, 时间,时区,或者数字几类。
如果一个数字记号包含一个冒号(:), 那么这是一个时间字串。包括随后所有的数据位和冒号。
如果这个数字记号包含一个划线(-),斜杠(/), 或者两个或多个点(.),那么它就是一个日期字串, 可能有一个文本月份。
如果这个记号只是数字,那么它要么是一个单独的字段, 要么是一个 ISO 8601 连接的日期(比如,19990113 是 1999 年一月 13 日)或者是连接的时间(比如,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。
技巧: 格里高利年份 AD 1-99可以用前导零的方式使用4位数字 (也就是说,0099 是 AD 99)。以前的 PostgreSQL 版本接受三位数字的年份和一位数字的年份,但是从版本 7.0 开始,这个 规则更严格了,以减少可能的混淆。