pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。
Postgres 支持全套 SQL 日期和时间类型。
表 3.7. Postgres 日期/时间类型
| 类型 | 描述 | 存储尺寸 | 最早 | 最晚 | 精度 |
|---|---|---|---|---|---|
timestamp |
日期和时间 | 8字节 | 4713 BC | AD 1465001 | 1微秒 / 14位 |
timestamp with time zone |
带时区的日期和时间 | 8字节 | 1903 AD | 2037 AD | 1微秒 / 14位 |
interval |
用于时间间隔 | 12字节 | -178000000年 | 178000000年 | 1微秒 |
date |
仅日期 | 4字节 | 4713 BC | 32767 AD | 1日 |
time |
仅一天中的时间 | 4字节 | 00:00:00.00 | 23:59:59.99 | 1微秒 |
time with time zone |
仅一天中的时间 | 4字节 | 00:00:00.00+12 | 23:59:59.99-12 | 1微秒 |
为确保与 Postgres 早期版本的兼容,我们还继续提供 datetime(等价于 timestamp)和 timespan(等价于 interval),但对它们的支持现在仅限于到 timestamp 和 interval 的隐式转换。abstime 和 reltime 类型是内部使用的低精度类型。不鼓励在新应用中使用这些类型,并建议在合适时把旧的迁移过去。这些内部类型中的任何一种或全部都可能在未来的版本中消失。
日期和时间输入几乎可以采用任何合理的格式,包括 ISO-8601、SQL 兼容格式、传统 Postgres 格式等。日期输入中月和日的顺序可能有歧义,因此有一个设置用于指定歧义情况下如何解释。命令 SET DateStyle TO 'US' 或 SET DateStyle TO 'NonEuropean' 指定"月在前"的变体,命令 SET DateStyle TO 'European' 则设置"日在前"的变体。ISO 风格是默认值,但这一默认可以在编译时或运行时改变。
关于日期/时间输入的精确解析规则和可识别的时区,参见 日期/时间支持。
请记住,任何日期或时间输入都必须像文本字符串一样用单引号括起来。
下面是 date 类型的一些可能输入。
表 3.8. Postgres 日期输入
| 示例 | 描述 |
|---|---|
| January 8, 1999 | 无歧义 |
| 1999-01-08 | ISO-8601 格式,推荐 |
| 1/8/1999 | 美式;在欧洲模式下读作 8 月 1 日 |
| 8/1/1999 | 欧式;在美式模式下读作 8 月 1 日 |
| 1/18/1999 | 美式;在任何模式下都读作 1 月 18 日 |
| 19990108 | ISO-8601 年、月、日 |
| 990108 | ISO-8601 年、月、日 |
| 1999.008 | 年和一年中的日子 |
| 99008 | 年和一年中的日子 |
| January 8, 99 BC | 公元前的 99 年 |
表 3.9. Postgres 月份缩写
| 月份 | 缩写 |
|---|---|
| April | Apr |
| August | Aug |
| December | Dec |
| February | Feb |
| January | Jan |
| July | Jul |
| June | Jun |
| March | Mar |
| November | Nov |
| October | Oct |
| September | Sep, Sept |
出于显而易见的原因,五月(May)没有明确的缩写。
表 3.10. Postgres 星期缩写
| 日 | 缩写 |
|---|---|
| Sunday | Sun |
| Monday | Mon |
| Tuesday | Tue, Tues |
| Wednesday | Wed, Weds |
| Thursday | Thu, Thur, Thurs |
| Friday | Fri |
| Saturday | Sat |
下面是有效的 time 输入。
表 3.11. Postgres 时间输入
| 示例 | 描述 |
|---|---|
| 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 |
| z | 和 00:00:00 一样 |
| zulu | 和 00:00:00 一样 |
| allballs | 和 00:00:00 一样 |
此类型由 SQL92 定义,但该定义存在根本性的缺陷,使这一类型几乎无法使用。在大多数情况下,date、 time 和 timestamp 的组合应能提供任何应用所需的完整日期/时间功能。
time with time zone 接受所有对 time 类型合法的输入,再加上一个合法的时区,如下:
表 3.12. Postgres 带时区的时间 输入
| 示例 | 描述 |
|---|---|
| 04:05:06.789-8 | ISO-8601 |
| 04:05:06-08:00 | ISO-8601 |
| 04:05-08:00 | ISO-8601 |
| 040506-08 | ISO-8601 |
更多时区的示例参见 Postgres 时区输入。
timestamp 类型的有效输入由一个日期和一个时间连接而成,其后可跟可选的 AD 或 BC,再后可跟可选的时区。(见下文。) 因而
1999-01-08 04:05:06 -8:00
是一个符合 ISO 的有效 timestamp 值。此外,还支持广泛使用的格式
January 8 04:05:06 1999 PST
也被支持。
表 3.13. Postgres 时区输入
| 时区 | 描述 |
|---|---|
| PST | 太平洋标准时间 |
| -8:00 | PST的ISO-8601偏移 |
| -800 | PST的ISO-8601偏移 |
| -8 | PST的ISO-8601偏移 |
interval 可用下列语法指定:
Quantity Unit [Quantity Unit...] [Direction]
@ Quantity Unit [Direction]
其中:Quantity(数量)是 ...、-1、 0、1、2、...; Unit(单位)是 second、 minute、hour、day、 week、month、year、 decade、century、millennium, 或者这些单位的缩写或复数形式; Direction(方向)可以是 ago 或 为空。
下面的函数与 SQL 兼容,可用作相应数据类型的日期或时间输入: CURRENT_DATE、 CURRENT_TIME、 CURRENT_TIMESTAMP。
Postgres 还为方便使用支持几种特殊常量。
表 3.14. Postgres 特殊日期/时间常量
| 常量 | 描述 |
|---|---|
| current | 当前事务时间,延迟求值 |
| epoch | 1970-01-01 00:00:00+00(Unix系统时间0) |
| infinity | 晚于其他有效时间 |
| -infinity | 早于其他有效时间 |
| invalid | 非法输入 |
| now | 当前事务时间 |
| today | 今天午夜 |
| tomorrow | 明天午夜 |
| yesterday | 昨天午夜 |
'now' 在插入值时解析,而 'current' 在每次取值时解析。所以在大多数应用中你可能想用 'now'。(当然,你真正想用的是 CURRENT_TIMESTAMP,它等价于 'now'。)
输出格式可以用 SET DateStyle 设为四种风格之一:ISO-8601、SQL(Ingres)、传统 Postgres 和德式。 默认是 ISO 格式。
表 3.15. Postgres 日期/时间输出风格
| 样式说明 | 描述 | 示例 |
|---|---|---|
| '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 |
date 和 time 风格的输出当然只是上述示例中相应的日期或时间部分。
SQL 风格有欧式和非欧式(美式)两种变体,它们决定月跟在日后还是日跟在月前。(另见上文“日期/时间输入”一节中关于此设置如何影响输入值解释的说明。)
表 3.16. Postgres 日期顺序惯例
| 样式说明 | 描述 | 示例 |
|---|---|---|
| European | day/month/year |
17/12/1997 15:37:16.00 MET |
| US | month/day/year |
12/17/1997 07:37:16.00 PST |
interval 的输出与输入格式相似,区别在于像 week 或 century 这样的单位会被转换为年和天。ISO 模式下输出形如
[ Quantity Units [ ... ] ] [ Days ] Hours:Minutes [ ago ]
有几种方法可以影响日期/时间类型的外观:
postmaster 启动时后端直接使用的 PGDATESTYLE 环境变量。
会话启动时前端 libpq 使用的 PGDATESTYLE 环境变量。
SET DATESTYLE SQL 命令。
Postgres 力求在典型用法上与 SQL92 定义兼容。但 SQL92 标准对日期和时间类型及能力有一种奇怪的组合。两个明显的问题是:
尽管 date 类型没有关联的时区,time 类型却可以或确实有关联的时区。
默认时区被指定为相对 GMT/UTC 的固定整数偏移。
现实世界中的时区若不同时关联日期和时间就可能没有意义,因为偏移量在一年中可能随夏令时边界而变化。
为解决这些困难,Postgres 只把时区关联到同时包含日期和时间的日期时间类型,而对只包含日期或只包含时间的类型假定使用本地时间。此外,时区支持源自底层操作系统的时区能力,因此可以处理夏令时和其他预期行为。
对于 1902 到 2038 年之间的日期,Postgres 从底层操作系统获得时区支持(接近 Unix 风格系统的典型日期界限)。在此范围之外,所有日期都假定以协调世界时(UTC)指定和使用。
所有日期和时间在内部都以 UTC(也称为格林尼治标准时间 GMT)存储。时间在发送给客户端前端之前会被转换为数据库服务器上的本地时间,因此默认情况下采用服务器时区。
有几种方法可以影响时区行为:
postmaster 启动时后端直接使用 TZ 环境变量作为默认时区。
在客户端设置的 PGTZ 环境变量由 libpq 用于在连接时向后端发送时区信息。
SQL 命令 SET TIME ZONE 设置会话的时区。
如果指定了无效的时区,时区会变成 GMT(至少在大多数系统上如此)。
如果设置了编译选项 USE_AUSTRALIAN_RULES,那么 EST 指的是澳大利亚东部标准时间,其偏移为相对 UTC +10:00 小时。
Postgres 在所有日期/时间计算中使用儒略日。它们有一个好的特性:能正确预测/计算从公元前 4713 年之后的任何日期 到遥远未来的任何日期,其假定是一年的长度为 365.2425 天。
19 世纪之前的日期约定读起来很有意思,但它们并不足够一致,不值得编码进日期/时间处理器。
译文有误、术语不当或页面显示问题,请到译文仓库 pgsty/pgdoc 报告译文问题。 英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。