↑↓ 选择↵ 打开⌫ 切换范围完整搜索

PG.CENTER 连接 PostgreSQL 文档、百科与生态知识。由 Pigsty 维护。

支持中的版本: 当前版本 (18) / 17 / 16 / 15 / 14
开发中的版本: 19 / 20devel
已结束支持的版本: 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.3 已结束支持。 请参阅 当前版本手册.

5.5. 日期/时间类型 #

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

表 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微秒

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

注意

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

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

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

time with time zone 类型由 SQL 标准定义,但该定义表现出一些使其用途令人怀疑的特性。在大多数情况下,date、time、timestamp without time zone 和 timestamp with time zone 的组合应能提供任何应用所需的完整日期/时间功能。

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

5.5.1. 日期/时间输入 #

日期和时间输入几乎可以采用任何合理的格式,包括 ISO 8601、SQL 兼容格式、传统 PostgreSQL 格式等。对于某些格式,日期输入中月和日的顺序可能有歧义,因此支持指定所期望的这些字段的顺序。命令 SET DateStyle TO 'US' 或 SET DateStyle TO 'NonEuropean' 指定“月在前”的变体,命令 SET DateStyle TO 'European' 则设置“日在前”的变体。

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

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

type [ (p) ] 'value'

其中可选精度说明中的 p 是一个对应于秒字段小数位数的整数。可以为 time、timestamp 和 interval types.

5.5.1.1. 日期

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

表 5.10. 日期输入

示例描述
January 8, 1999无歧义
1999-01-08ISO-8601 格式,推荐
1/8/1999美式;在欧洲模式下读作 8 月 1 日
8/1/1999欧式;在美式模式下读作 8 月 1 日
1/18/1999美式;在任何模式下都读作 1 月 18 日
19990108ISO-8601 年、月、日
990108ISO-8601 年、月、日
1999.008年和一年中的日子
99008年和一年中的日子
J2451187儒略日
January 8, 99 BC公元前99年

5.5.1.2. 时间

time 类型可以写作 time 或 time without time zone。可选精度 p 应在 0 到 6 之间,默认取输入时间字面量的精度。

表 5.11列出了有效的 time 输入。

表 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 类型合法的输入,再加上一个合法的时区,如表 5.12所示。

表 5.12. 带时区的时间输入

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

更多时区的示例参见表 5.13。

5.5.1.3. 时间戳

时间戳类型是 timestamp [ (p) ] without time zone 和 timestamp [ (p) ] with time zone。单独写 timestamp 等价于 timestamp without time zone。

注意

在 PostgreSQL 7.3 之前,只写 timestamp 等价于 timestamp with time zone。为符合 SQL 规范,这一点已被改变。

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

1999-01-08 04:05:06

和

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

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

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 构造(见第 6.8.3 节)。

timestamp without time zone 与 timestamp with time zone 之间的转换通常假定 timestamp without time zone 值应按 TimeZone 本地时间对待。可以用 AT TIME ZONE 为转换指定不同的时区参照。

表 5.13. 时区输入

Time Zone描述
PST太平洋标准时间
-8:00PST的ISO-8601偏移
-800PST的ISO-8601偏移
-8PST的ISO-8601偏移

5.5.1.4. 间隔

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

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

其中:Quantity(数量)是一个数字(可带符号);Unit(单位)是 second、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_DATE、CURRENT_TIME、CURRENT_TIMESTAMP。后两个函数接受可选的精度说明。(另见第 6.8.4 节。)

PostgreSQL 还为方便使用支持几种特殊日期/时间输入值,如表 5.14。值 infinity 和 -infinity 在系统内部有特殊的表示并以相同方式显示;其余的只是记法上的简写,读取时会被转换为普通的日期/时间值。

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

输入串描述 
epoch1970-01-01 00:00:00+00(Unix系统时间0) 
infinity晚于所有其他时间戳(类型 date 不可用) 
-infinity早于所有其他时间戳(类型 date 不可用) 
now当前事务时间 
today今天午夜 
tomorrow明天午夜 
yesterday昨天午夜 
zulu, allballs, z00:00:00.00 GMT 

5.5.2. 日期/时间输出 #

输出格式可以用 SET DateStyle 设为四种风格之一:ISO 8601、SQL(Ingres)、传统 PostgreSQL 和德式。默认是 ISO 格式。(SQL 标准要求使用 ISO 8601 格式。“SQL” 输出格式这一名称是历史的偶然。)表 5.15给出了每种输出风格的示例。date 和 time 类型的输出当然只是所给示例中相应的日期或时间部分。

表 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 风格有欧式和非欧式(美式)两种变体,它们决定月跟在日后还是日跟在月后;反之亦然。(关于此设置如何影响输入值的解释,参见第 5.5.1 节。)表 5.16给出了一个示例。

表 5.16. 日期顺序习惯

样式说明描述示例
Europeanday/month/year17/12/1997 15:37:16.00 MET
USmonth/day/year12/17/1997 07:37:16.00 PST

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

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

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

5.5.3. 时区 #

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

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

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

为解决这些困难,我们建议在使用时区时选用同时包含日期和时间的日期/时间类型。我们建议不要使用 time with time zone 类型(尽管为了旧应用以及与其他 SQL 实现的兼容,PostgreSQL 支持它)。对于只包含日期或只包含时间的类型,PostgreSQL 假定使用你的本地时区。此外,时区支持源自底层操作系统的时区能力,因此可以处理夏令时和其他预期行为。

对于 1902 到 2038 年之间的日期,PostgreSQL 从底层操作系统获得时区支持(接近 Unix 风格系统的典型日期界限)。在此范围之外,所有日期都假定以协调世界时(UTC)指定和使用。

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

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

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

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

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

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

注意

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

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

5.5.4. 内部实现 #

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

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

报告文档问题

阅读 上游文档. 反馈更正前请先核对 当前版本手册.