5.5. 日期/时间类型

PostgreSQL 支持 SQL 中所有的日期和时间类型。 在 Table 5-9 中显示。

Table 5-9. 日期/时间类型

类型描述存储最早最晚分辨率
timestamp [ (p) ] [without time zone]包括日期和时间8 字节4713 BCAD 14650011 毫秒 / 14 位
timestamp [ (p) ] with time zone日期和时间8 字节4713 BCAD 14650011 毫秒 / 14 位
interval [ (p) ]时间间隔12 字节-178000000 年178000000 年1 毫秒
date只用于日期4 字节4713 BC32767 AD1 天
time [ (p) ] [ without time zone ]只用于一日内时间8 字节00:00:00.0023:59:59.991 毫秒
time [ (p) ] with time zone只用于一日内时间12 字节00:00:00.00+1223:59:59.99-121 毫秒

timetimestampinterval 接受一个可选的 精度值 p,这个精度值声明在秒域后面 小数点之后保留的位数.缺省的时候在精度上是没有明确的绑定的, p 有用的范围对 timestampinterval 是从 0 到大约 6, 对 time 是从 0 到 13。

注意: 如果 timestamp 数值是以双精度浮点数(目前的缺省)的方式存储的, 那么精度的有效限制会小于 6,因为 timestamp 值是以自 2000-01-01 以来的 秒数存储的。微秒的精度是为那些在 2000-01-01 前后几年的日期实现的, 对于那些远一些的日子,精度会下降。如果 timestamp 以八字节整数存储 (一个编译时的选项),那么微秒的精度就可以在数值的全部范围内都可以获得。

时区和时区习惯都是受政治习惯影响,不仅仅受地球地理因素影响. 在 19 世纪里,全球的时区慢慢变得更标准化了一些,但是仍然容易遭受 随意的修改.PostgreSQL 使用你的 操作系统下层的特性提供时区支持,并且这些系统通常只包含 1902 年到 2038 年之间的信息(对应于传统 Unix 系统时间的完整跨度). timestamp with time zonetime with time zone 将只在这个年代范围内使用时区信息, 如果时间超过这个范围,那么假设时间是 UTC.

类型time with time zone是 SQL 标准定义的, 但是但是整个定义有些方面会导致有问题的用法。在大多数情况下, datetimetimestamp without time zonetimestamp with time zone 的组合就应该能提供提供 任何应用需要的日期/时间的完整功能。

类型 abstimereltime 是低分辨率类型,它们被用于系统内部。 我们不鼓励你在新的应用里面使用这些类型,同时我 们支持合适的时候把旧应用中对应的类型转换成目前上面指明的。 因为这些旧类型的部分或全部可能会在未来的版本里消失。

5.5.1. 日期/时间输入

日期和时间的输入几乎可以是任何合理的格式,包括 ISO 8601SQL-兼容的, 传统 PostgreSQL 的和其他的形式。 对于一些格式,日期输入里的月份和日子输入可能会让人模糊, 因此系统里有一些支持方法可以用来声明自己预期的这些字段的顺序. 命令 SET DateStyle TO 'US'SET DateStyle TO 'NonEuropean' 表示设置为“月份在日子前面”,而命令 SET DateStyle TO 'European' 表示设置为“日子在月份前面”。

PostgreSQL 在处理日期/时间上比 SQL 标准要求的更灵活. 参阅 Appendix A 获取关于日期/时间输入的准确的分析规则和可识别文本字段, 包括月份,星期几,和时区.

请记住任何日期或者时间的文本输入需要由单引号包围, 就象一个文本字符串一样。 参考 Section 1.1.2.4 获取更多信息.SQL 要求下面的语法

type [ (p) ] 'value'

在这里可选的精度声明中的 p 是一个整数, 对应在秒域中小数部分的位数, 我们可以对 timetimestamp,和 interval 类型声明精度.

5.5.1.1. 日期

Table 5-10 显示了 date 类型可能的输入方式。

Table 5-10. 日期输入

例子描述
January 8, 1999无歧义
1999-01-08ISO-8601 格式,建议方式
1/8/1999U.S.;在 European 模式下读做八月一日
8/1/1999European;在 U.S. 模式下读做八月一日
1/18/1999U.S.;在任何模式下都读做一月十八日
19990108ISO-8601 年,月,日
990108ISO-8601 年,月,日
1999.008年和年里的第几天
99008年和年里的第几天
J2451187Julian day
January 8, 99 BC公元前99年

5.5.1.2. 时间

类型 time 可以声明为 time 或者 time without time zone(不带时区时间). 可选的精度应该介于 0 和 13 之间,缺省是输入时间文本的精度.

Table 5-11显示了有效的 time (时间)输入.

Table 5-11. 时间输入

例子描述
04:05:06.789ISO 8601
04:05:06ISO 8601
04:05ISO 8601
040506ISO 8601
04:05 AM与 04:05 一样;AM 不影响数值
04:05 PM与 16:05一样;输入小时数必须 <= 12
allballs与 00:00:00 一样

time with time zone 接受所有对 time 类型也合法的输入,附加一个合法的时区,如下表 显示 Table 5-12

Table 5-12. time with time zone 输入

例子描述
04:05:06.789-8ISO 8601
04:05:06-08:00ISO 8601
04:05-08:00ISO 8601
040506-08ISO 8601

参考 Table 5-13 获取更多时区的例子。

5.5.1.3. 时间戳

时间戳类型是 timestamp [(p) ] without time zonetimestamp [ (p) ] with time zone。 只写 timestamp 等效于 timestamp without time zone

注意: PostgreSQL 7.3 之前,只写 timestamp 等效于 timestamp with time zone。 这个改变是为了和 SQL 规范兼容。

timestamp 类型的有效输入由一个 日期和时间的联接组成,后面跟着一个可选的 AD 或者 BC,然后再跟着可选的时区.(见Table 5-13.) 因此

1999-01-08 04:05:06

1999-01-08 04:05:06 -8:00

是一个有效的 timestamp without time zone 数值, 它是兼容 ISO 的.另外,下面这种使用广泛的格式

January 8 04:05:06 1999 PST

也受支持.

可选的精度 p 应该介于 0 和 6 之间, 缺省是输入 timestamp 文本的精度.

对于 timestamp without time zone,任何在输入中 声明的时区都被悄悄吞掉.也就是说,生成的日期/时间数值是从 输入中明确的日期/时间字段中得出的,并且没有根据时区调整.

对于 timestamp with time zone,内部存储的数值总是 UTC (GMT)。如果一个输入值又明确的时区声明,那么它将用该时区合适 的偏移量转换成 UTC。如果在输入字串里没有时区声明,那么它就假设是 在系统的 TimeZone 参数里的那个时区,然后使用这个 TimeZone 时区转换成 UTC。

如果输出一个 timestamp with time zone,那么它总是从 UTC 转换成当前的 TimeZone 时区,并且显示为改时区的本地时间。 要看其它时区的该时间,要么修改 TimeZone,要么使用 AT TIME ZONE 构造(参阅 Section 6.8.3)。

timestamp without time zonetimestamp with time zone 之间的转换通常假设 timestamp without time zone 数值应该以 TimeZone 本地时间的形式接受或者写出。 其它得时区引用可以用 AT TIME ZONE 的方式为转换声明。

Table 5-13. 时区输入

时区描述
PST太平洋标准时间(Pacific Standard Time)
-8:00ISO-8601 与 PST 的偏移
-800ISO-8601 与 PST 的偏移
-8ISO-8601 与 PST 的偏移

5.5.1.4. 间隔

interval数值可以用下面语法声明:

  Quantity Unit [Quantity Unit...] [Direction]
@ Quantity Unit [Quantity Unit...] [Direction]
      

这里:Quantity 是一个数字(可能有符号); Unitsecond, minute, hour, day, week, month, year, decade, century, millennium, 或者这些单位的缩写或复数; Direction 可以是 ago 或者为空。符号 @ 是一个可选的杂音.不同的单位以及相应 正确的符号都是隐含地增加的.

日期,小时,分钟,以及秒钟的数量可以在无明确单位标记的情况下声明. 比如,'1 12:59:10''1 day 12 hours 59 min 10 sec' 读数一样.

可选的精度 p 应该介于 0 和 6 之间, 并且缺省是输入文本的精度.

5.5.1.5. 特殊值

下面的 SQL-兼容的函数可以用于 对应的数据类型的日期或时间输入: CURRENT_DATECURRENT_TIMECURRENT_TIMESTAMP。 后面两个接受一个可选的精度声明. (又见 Section 6.8.4。)

PostgreSQL 为方便起见同样还支持几个特殊输入值, 如在 Table 5-14 里面显示的那样。 值infinity-infinity 是特别在系统内部表示的,并且将按照同样的方式显示; 但是其它的都只是符号缩写,在读取的时候将呗转换成普通的日期/时间值。

Table 5-14. 特殊日期/时间输入

输入字串描述
epoch1970-01-01 00:00:00+00 (Unix 系统零时)
infinity比任何其它时间戳都晚(不能用于类型date
-infinity比任何其它时间戳都早(不能用于类型date
invalid非法输入
now当前事务时间
today今日午夜
tom或者row明日午夜
yesterday昨日午夜
zulu, allballs, z00:00:00.00 GMT

5.5.2. 日期/时间输出

使用 SET DateStyle,输出格式可以设成四种风格之一: ISO 8601,SQL (Ingres),传统的 PostgreSQL,和 German 。缺省是 ISO 格式。 (SQL 标准要求使用 ISO 8601 格式。"SQL" 输出格式的名字是历史偶然。)Table 5-15 显示了每种输出风格的例子。datetime 类型的 输出当然只是给出的例子里面的日期和时间部分。

Table 5-15. 日期/时间输出风格

风格描述描述例子
ISOISO-8601/SQL 标准1997-12-17 07:37:16-08
SQL传统风格12/17/1997 07:37:16.00 PST
PostgreSQL原始风格Wed Dec 17 07:37:16 1997 PST
German地区风格17.12.1997 07:37:16.00 PST

SQL 风格有欧洲和非欧洲(U.S.)变种, 决定月份后面是日期还是正相反.(参阅 Section 5.5.1 分,看看这个设置是如何影响对输入值的解释。) Table 5-16 显示了一个例子。

Table 5-16. 日期顺序习惯

风格描述描述例子
European//17/12/1997 15:37:16.00 MET
US//12/17/1997 07:37:16.00 PST

interval 的输出看起来象输入格式,只是象 weekcentury 这样的单位被转换成年和日。在 ISO 模式下输出看起来象

[ Quantity Units [ ... ] ] [ Days ] Hours:Minutes [ ago ]

日期/时间风格可以由用户用 SET DATESTYLE 命令 选取,或者在 postgresql.conf 配置文件里的参数 datestyle 设置,或者服务器或客户端的 PGDATESTYLE 环境变量里设置。我们也可以用格式化函数 to_char(参阅 Section 6.7) 来更灵活地控制时间/日期地输出。

5.5.3. 时区

PostgreSQL 在典型应用中尽可能与 SQL 的定义相兼容.但 SQL 标准在日期和时间类型 和功能上有一些奇怪的混淆.两个显而易见的问题是:

为了克服这些困难,我们建议在使用时区的时候, 使用那些同时包含日期和时间的日期/时间类型. 我们建议不要使用类型 time with time zone (尽管 PostgreSQL 出于合理应用以及为了与其他RDBMS实现兼容的考虑支持这个类型). PostgreSQL 假设你用于任何类型的本地时区 都只包含日期或时间.而且,时区支持是源自下层操作系统的时区功能. 因此可以对付夏时制和其他可预料的性质.

PostgreSQL 从操作系统获得介于1902年和2038年的日期的时区支持 (近乎是典型的Unix类系统的日期限 制).在这个范围之外的日期都假设为用全球统一时间 (Universal Coordinated Time,UTC)声明和使用。

在系统内部,所有日期和时间都是用全球统一时间(UTC)格式存储, 也就是通常所说的格林威治时间(GMT). 时间在发给客户前端前由数据库服务器转换成本地时间, 因而缺省的时区是服务器的时区.

有好几种选取服务器使用的时区的方法:

注意: 如果使用了非法的时区,时区变为 GMT(在大多数系统上)。

请参考 Appendix A 获取一个可用 时区的列表。

5.5.4. 内部

PostgreSQL 使用 Julian 记日法用于所有日期/时间计算。 如果假设一年的长度是365.2425天时,这个方法可以 很精确地预计/计算从4713 BC(公元前4713年)到很久的未来的任意一天的日期。

19世纪以前的日期传统(历法)对一些趣味读物有意义, 但是在我们这里好象没有充分的理由把它们编码入日 期/时间控制器里面去。