3.4. 日期/时间类型

Postgres 支持 SQL 中所有的日期和时间类型。

Table 3-6. 日期/时间类型

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

注意: 为了保证和早期 Postgres 版本的兼容, 我们还继续提供 datetime (等效于 timestamp)和 timespan(等效于 interval)。 不过对这些类型的支持现在局限于 进行一个隐含的转换,转换成 timestampinterval。 类型 abstimereltime 是低分辨率类型,它们被用于系统内部。 我们不鼓励你在新的应用里面使用这些类型,同时我 们支持合适的时候把旧应用中对应的类型转换成目前上面指明的。 因为这些旧类型的部分或全部可能会 在未来的版本里消失。

3.4.1. 日期/时间输入

日期和时间的输入几乎可以是任何合理的格式,包括 ISO-8601SQL-兼容的, 传统 Postgres 的和其他的形式。 日期输入里的月份和日子输入可能会让人模糊, 因此存在一个设置用于表明具体应该如何解释。 命令 SET DateStyle TO 'US'SET DateStyle TO 'NonEuropean' 表示设置为“月份在日子前面”,而命令 SET DateStyle TO 'European' 表示设置为“日子在月份前面”。缺省是 ISO 风格,但是缺省值可以在编译或者运行时改变。

参阅 Appendix A 获取关于日期/时间输入的准确的分析规则和可识别的时区的信息。

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

type 'value'
不过 Postgres 更灵活.

3.4.1.1. date(日期)

下表是 date 类型可能的输入方式。

Table 3-7. 日期输入

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

Table 3-8. 月份缩写

月份缩写
April(四月)Apr
August(八月)Aug
December(十二月)Dec
February(二月)Feb
January(一月)Jan
July(七月)Jul
June(六月)Jun
March(三月)Mar
November(十一月)Nov
October(十月)Oct
September(九月)Sep, Sept

注意: 五月 (May)没有明确的缩写,原因是显而易见的。

Table 3-9. 周日缩写

周日缩写
Sunday(星期天)Sun
Mondayi(星期一)Mon
Tuesdayi(星期二)Tue, Tues
Wednesday(星期三)Wed, Weds
Thursday(星期四)Thu, Thur, Thurs
Friday(星期五)Fri
Saturday(星期六)Sat

3.4.1.2. time [ without time zone ]

根据 SQL99,这个类型可以称为 timetime without time zone(不带时区时间)

下面是有效的 time (时间)输入.

Table 3-10. 时间输入

例子描述
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
z与 00:00:00 一样
zulu与 00:00:00 一样
allballs与 00:00:00 一样

3.4.1.3. 带时区时间

这个类型是 SQL92 定义的,但是该定义显示出非常基本的不足, 令这个类型几乎无用。在多数情况下, datetime,和 timestamp 的组合应该能提供任何应用所需要的日期/时间功能的全部内容。

带时区时间 接受所有对 time 类型也合法的输入,附加一个合法的时区,如下:

Table 3-11. 带时区时间输入

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

参考 Table 3-12 获取更多时区的例子。

3.4.1.4. timestamp

有效的 timestamp 类型的输入包含一个日期和一个时间的连接, 后面跟着可选的 ADBC,再后面跟着 可选的时区。(参阅下面。)因此

1999-01-08 04:05:06 -8:00
      
是一个有效的 timestamp 值,它是 ISO-兼容的。另外,已经广泛使用的格式
January 8 04:05:06 1999 PST
      
也是支持的。

Table 3-12. 时区输入

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

3.4.1.5. interval(时间间隔)

interval可以用下面语法声明:

  Quantity Unit [Quantity Unit...] [Direction]
@ Quantity Unit [Direction]
      
这里:Quantity 是 ..., -1, 0, 1, 2, ...; Unitsecond, minute, hour, day, week, month, year, decade, century, millennium, 或者这些单位的缩写或复数; Direction 可以是 ago 或者为空。

3.4.1.6. 特殊值

下面的 SQL-兼容的函数可以用于对应的数据类型的日期或时间输入: CURRENT_DATECURRENT_TIMECURRENT_TIMESTAMP

Postgres 为方便起见同样还支持几个特殊常量。

Table 3-13. 日期/时间特殊常量

常量描述
current当前事务时间, (使用时)deferred
epoch1970-01-01 00:00:00+00 (Unix 系统零时)
infinity比任何有效时间晚
-infinity比任何有效时间早
invalid非法输入
now当前事务时间
today今日午夜
tomorrow明日午夜
yesterday昨日午夜
'now' 在该值被插入时解释,'current' 在每次检索该值时被解释。所以你可能会在大多数应用里使用 'now' 。(当然你 really 地想用 CURRENT_TIMESTAMP的话也行,它等效于 'now'。)

3.4.2. 日期/时间输出

使用 SET DateStyle,输出格式可以设成四种风格之一: ISO-8601,SQL (Ingres),传统的 Postgres,和 German 。缺省是 ISO 格式。

Table 3-14. 日期/时间输出风格

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

datetime 风格的输出当然只是对应上面例子的日期或者时间部分。

SQL 风格有欧洲和非欧洲(US)变种, 决定月份后面是日期还是正相反.(参阅上面日期/时间输入部 分,看看这个设置是如何影响对输入值的解释。)

Table 3-15. 日期顺序传统

风格描述描述例子
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 ]

有几种方法可以影响日期/时间类型的输出:

3.4.3. 时区

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

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

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

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

有几种影响时区特性的方法:

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

注意: 如果设置了编译选项 USE_AUSTRALIAN_RULES,那么 那么 EST 代表澳大利亚东部标准时间, ( Australia Eastern Std Time)与 UTC 有 +10:00 小时的偏移量。

3.4.4. 内部

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

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