↑↓ 选择 ↵ 打开 ⌫ 改范围 完整检索页

pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。

受支持版本: 当前版本 (18) / 17 / 16 / 15 / 14
测试与开发版本: 19 / devel
不受支持的版本: 13 / 12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0 / 8.4 / 8.3 / 8.2 / 8.1 / 8.0 / 7.4 / 7.3 / 7.2 / 7.1
历史版本PostgreSQL 7.4 已于 2010 年 10 月结束社区维护,本页译文保留供仍在使用旧版本的读者参考。新系统请看当前版本。

8.5. 日期/时间类型 #

PostgreSQL 支持全套 SQL 日期和时间类型,如 表 8.9 所示。

表 8.9. 日期/时间类型

名字 存储尺寸 描述 低值 高值 精度
timestamp [ (p) ] [ without time zone ] 8字节 日期和时间 4713 BC 5874897 AD 1微秒 / 14位
timestamp [ (p) ] with time zone 8字节 包括日期和时间,有时区 4713 BC 5874897 AD 1微秒 / 14位
interval [ (p) ] 12字节 时间间隔 -178000000年 178000000年 1微秒
date 4字节 仅日期 4713 BC 32767 AD 1日
time [ (p) ] [ without time zone ] 8字节 仅一天中的时间 00:00:00.00 23:59:59.99 1微秒
time [ (p) ] with time zone 12字节 仅一天中的时间,带时区 00:00:00.00+12 23:59:59.99-12 1微秒

注意

在 PostgreSQL 7.3 之前的版本中,仅写timestamp等效于timestamp with time zone。为了符合 SQL 标准,这一行为已被改变。

time、timestamp 和 interval 都接受一个可选精度值 p,用来指定在秒字段中 保留多少位小数。默认情况下,对精度没有显式上界。 对于 timestamp 和 interval 类型, p 的允许范围是 0 到 6。

注意

当 timestamp 值以双精度浮点数存储(目前的默认方式)时,精度的有效上限可能小于 6。timestamp 值存储为相对 2000-01-01 午夜之前或之后的秒数。对 2000-01-01 前后几年的日期可以达到微秒精度,但对更远的 日期,精度会进一步降低。当 timestamp 值以八字节整数存储(一种编译期选项)时,全部取值范围内都有微秒精度。但八字节整数时间戳的日期范围比上表所示的更有限:从公元前 4713 年到公元 294276 年。

对于 time 类型,采用八字节整数存储时, p 的允许范围是 0 到 6;采用浮点存储时, 允许范围是 0 到 10。

time with time zone 类型由 SQL 标准定义,但其定义具有 一些会让人怀疑其实用性的特性。在大多数情况下, date、time、 timestamp without time zone 和 timestamp with time zone 的组合,就足以提供任何应用 所需的完整日期/时间功能。

类型abstime和reltime是内部使用的低精度类型。不推荐在应用中使用这些类型;这些内部类型可能在将来的版本中消失。

8.5.1. 日期/时间输入 #

日期和时间输入几乎可以采用任何合理的格式,包括 ISO 8601、SQL 兼容格式、传统 POSTGRES 格式等。对于某些格式,日期输入中月、日、年的顺序可能有歧义,因此支持指定所期望的 这些字段的顺序。将 datestyle 参数设为 MDY 可选择月-日-年解释,设为 DMY 可选择日-月-年解释,设为 YMD 可选择年-月-日解释。

PostgreSQL 在处理日期/时间输入方面, 比 SQL 标准要求的更灵活。有关日期/时间输入的 精确解析规则,以及可识别的文本字段(包括月份、星期几和时区), 请参见 附录 B。

请记住,任何日期或时间字面值输入都必须像文本字符串一样用单引号 括起来。更多信息请参见 第 4.1.2.4 节。 SQL 要求使用下列语法:

type [ (p) ] 'value'

其中 p 是可选的精度说明,给出秒字段中 保留的小数位数。精度可用于 time、 timestamp 和 interval 类型, 允许的取值范围见上文。如果在常量声明中没有指定 精度,则默认采用该字面值本身的精度。

8.5.1.1. 日期

表 8.10显示了date类型可能的输入方式。

表 8.10. 日期输入

示例 描述
January 8, 1999 在任何datestyle输入模式下都无歧义
1999-01-08 ISO 8601;任何模式下的1月8日 (推荐格式)
1/8/1999 MDY模式中的1月8日;DMY模式中的8月1日
1/18/1999 MDY模式中的1月18日;在其他模式中被拒绝
01/02/03 MDY模式中的2003年1月2日; DMY模式中的2003年2月1日; YMD模式中的2001年2月3日
1999-Jan-08 任何模式下的1月8日
Jan-08-1999 任何模式下的1月8日
08-Jan-1999 任何模式下的1月8日
99-Jan-08 YMD模式中的1月8日,否则错误
08-Jan-99 1月8日,除了在YMD模式中错误
Jan-08-99 1月8日,除了在YMD模式中错误
19990108 ISO 8601;任何模式中的1999年1月8日
990108 ISO 8601;任何模式中的1999年1月8日
1999.008 年和一年中的日子
J2451187 儒略日
January 8, 99 BC 公元前99年

8.5.1.2. 时间

一天中的时间类型包括 time [ (p) ] without time zone 和 time [ (p) ] with time zone。 单独写 time 等效于 time without time zone。

这些类型的有效输入由一个一天中的时间,加上一个可选时区组成 (见 表 8.11 和 表 8.12)。如果在 time without time zone 的输入中指定了时区,它会被 静默忽略。

表 8.11. 时间输入

示例 描述
04:05:06.789 ISO 8601
04:05:06 ISO 8601
04:05 ISO 8601
040506 ISO 8601
04:05 AM 和04:05一样,AM并不影响值
04:05 PM 和16:05一样;输入的小时必须 <= 12
04:05:06.789-8 ISO 8601
04:05:06-08:00 ISO 8601
04:05-08:00 ISO 8601
040506-08 ISO 8601
04:05:06 PST 名称指定的时区

表 8.12. 时区输入

示例 描述
PST 太平洋标准时间
-8:00 PST的ISO-8601偏移
-800 PST的ISO-8601偏移
-8 PST的ISO-8601偏移
zulu UTC的军方缩写
z zulu的缩写形式

8.5.1.3. 时间戳

时间戳类型的有效输入由一个日期和一个时间连接而成,其后可跟可选的 AD 或 BC,再后可跟可选的时区。因此

1999-01-08 04:05:06

和

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

都是有效的值,它们遵循 ISO 8601 标准。此外,还支持广泛使用的格式

January 8 04:05:06 1999 PST

也被支持。

对于 timestamp [without time zone],输入中指定的任何显式时区都会被静默忽略。也就是说, 得到的日期/时间值由输入值中显式的日期/时间字段导出,不随时区调整。

对于 timestamp with time zone,内部存储的值总是 UTC(Universal Coordinated Time,传统上称为格林尼治标准时间 GMT)。指定了显式时区的输入值会按该时区的相应偏移转换为 UTC。如果输入串中没有给出时区,则假定它位于系统 timezone 参数指示的时区,并按 timezone 时区的偏移转换为 UTC。

当输出一个 timestamp with time zone 值时,它总会从 UTC 转换到当前 timezone 时区,并显示为该时区的 本地时间。若要查看其他时区的时间,可以修改 timezone,或者使用 AT TIME ZONE 构造(见 第 9.8.3 节)。

在 timestamp without time zone 和 timestamp with time zone 之间转换时,通常假定 timestamp without time zone 值应被解释为,或输出为, timezone 本地时间。要为该转换指定不同的时区, 可以使用 AT TIME ZONE。

8.5.1.4. 间隔

interval值可以用下列语法书写:

[@] quantity unit [quantity unit...] [direction]

其中:quantity是一个数字(可带符号); unit是second、 minute、hour、day、 week、month、year、 decade、century、millennium, 或者这些单位的缩写或复数形式; direction可以是ago或为空。 at 符号(@)是可选的噪音。不同单位的数量会带 着适当的符号被隐式地累加起来。

天、小时、分钟和秒的数量可以不带显式的单位标记来指定。 例如,'1 12:59:10'的读法与 '1 day 12 hours 59 min 10 sec'相同。

可选的精度p应当在 0 到 6 之间, 默认为输入字面量的精度。

8.5.1.5. 特殊值

下面的函数与 SQL 兼容,可用作相应数据类型的日期或时间值: CURRENT_DATE、CURRENT_TIME、 CURRENT_TIMESTAMP、LOCALTIME、 LOCALTIMESTAMP。后四个函数接受可选的精度说明。(另见 第 9.8.4 节。)

PostgreSQL 还为方便使用支持几种 特殊日期/时间输入值,如 表 8.13 所示。值 infinity 和 -infinity 在系统内部有特殊的表示并以相同方式显示;其余的只是记法上的简写,读取时会被转换为普通的日期/时间值。所有这些值都被当作普通常量处理,需要写成单引号括起来的形式。

表 8.13. 特殊日期/时间输入

输入字符串 有效类型 描述
epoch date, timestamp 1970-01-01 00:00:00+00(Unix系统时间0)
infinity timestamp 晚于所有其他时间戳
-infinity timestamp 早于所有其他时间戳
now date, time, timestamp 当前事务的开始时间
today date, timestamp 今天午夜
tomorrow date, timestamp 明天午夜
yesterday date, timestamp 昨天午夜
allballs time 00:00:00.00 UTC

8.5.2. 日期/时间输出 #

日期/时间类型的输出格式可以设为四种样式之一:ISO 8601、SQL(Ingres)、传统的 POSTGRES 和 German,这通过命令SET datestyle设置。默认是ISO格式。(SQL标准要求使用 ISO 8601 格式。之所以存在名为“SQL”的输出格式,只是历史原因。)表 8.14展示了各种输出样式的示例。date和time类型的输出当然只包含给定示例中相应的日期部分或时间部分。

表 8.14. 日期/时间输出风格

样式说明 描述 示例
ISO ISO 8601/SQL 标准 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

SQL和POSTGRES风格中,如果指定了 DMY 字段顺序,“日”将出现在“月”之前,否则“月”出现在“日”之前(有关该设置如何影响输入值的解释,请参考第 8.5.1 节)。表 8.15给出了示例。

表 8.15. 日期顺序习惯

datestyle 设置 输入顺序 输出示例
SQL, DMY day/month/year 17/12/1997 15:37:16.00 CET
SQL, MDY month/day/year 12/17/1997 07:37:16.00 PST
Postgres, DMY day/month/year Wed 17 Dec 07:37:16 1997 PST

interval 的输出与输入格式相似,区别在于像 century 或 wek 这样的单位会被转换为年和天,并且 ago 会被转换为适当的符号。在 ISO 模式下输出形如

[ quantity unit [ ... ] ] [ days ] [ hours:minutes:sekunden ]

用户可以用 SET datestyle 命令、 postgresql.conf 配置文件中的 datestyle 参数,或服务器/客户端上的 PGDATESTYLE 环境变量来选择日期/时间风格。格式化函数 to_char(见 第 9.7 节)也可作为一种更灵活的日期/时间输出格式化手段。

8.5.3. 时区 #

时区及时区惯例受政治决策的影响,而不只是地球几何。世界各地的时区在 20 世纪期间变得多少标准化了一些,但仍容易发生任意的变更。PostgreSQL 使用操作系统的底层特性来提供输出时区支持,而这些系统通常只包含 1902 到 2038 年期间的信息(对应传统 Unix 系统时间的全部范围)。timestamp with time zone 和 time with time zone 只在该年份范围内使用时区信息,并假定范围外的时间位于 UTC。不过由于时区支持源自底层操作系统的时区能力,它可以处理夏令时和其他特殊行为。

PostgreSQL 力求在典型用法上与 SQL 标准定义兼容。但 SQL 标准对日期和 时间类型和能力方面有一种奇怪的组合。两个明显的问题是:

  • 尽管 date 类型没有关联的时区,time 类型却可以有关联的时区。现实世界中的时区若不同时关联日期和时间就可能没有意义,因为偏移量在一年中可能随夏令时边界而变化。

  • 默认时区被指定为相对 UTC 的固定数字偏移。在跨 DST 边界进行日期/时间运算时无法适应夏令时。

为解决这些困难,我们建议在使用时区时选用同时包含日期和时间的日期/时间类型。我们建议不要使用 time with time zone 类型(尽管为了旧应用以及与其他 SQL 实现的兼容,PostgreSQL 支持它)。对于只包含日期或只包含时间的类型,PostgreSQL 假定使用你的本地时区。

所有日期和时间在内部都以 UTC 存储。时间在发送给客户端之前会被转换为数据库服务器上的本地时间,因此默认情况下采用服务器时区。

有几种方法可以选择服务器使用的时区:

  • 如果没有指定其他时区,服务器主机上的 TZ 环境变量将被服务器用作默认时区。

  • timezone 配置参数可以在文件 postgresql.conf 中设置。

  • libpq客户端使用PGTZ环境变量在连接时向服务器发送SET TIME ZONE命令。

  • SQL 命令 SET TIME ZONE 设置会话的时区。

注意

如果指定了无效的时区,时区会变成 UTC(至少在大多数系统上如此)。

有关可用时区的列表,请参见附录 B。

8.5.4. 内部实现 #

PostgreSQL在所有日期/时间计算中使用儒略日。这带来一个有用的特性:在假定一年长度为 365.2425 天的前提下,能够正确计算从公元前 4713 年到遥远未来的日期。

19 世纪之前的日期约定读起来很有意思,但它们并不足够一致,不值得写进日期/时间处理器中。

提交更正

译文有误、术语不当或页面显示问题,请到译文仓库 pgsty/pgdoc 报告译文问题。 英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。