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

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.3 已于 2007 年 11 月结束社区维护,本页译文保留供仍在使用旧版本的读者参考。新系统请看当前版本。

6.8. 日期/时间函数和操作符 #

表 6.18 展示了可用于 日期/时间值处理的函数,细节在 随后的小节中给出。表 6.17 图解了 基本算术操作符(+、 * 等)的行为。格式化函数请参阅 第 6.7 节。你应当熟悉 日期/时间数据类型的背景信息(见第 5.5 节)。

下文描述的所有接受 time 或 timestamp 输入的函数和操作符实际上都有两个变体:一个接受带 时区的 time 或 timestamp,另一个接受不带 时区的 time 或 timestamp。 为简洁起见,这些变体没有单独列出。

表 6.17. 日期/时间操作符

名称 示例 结果
+ timestamp '2001-09-28 01:00' + interval '23 hours' timestamp '2001-09-29 00:00'
+ date '2001-09-28' + interval '1 hour' timestamp '2001-09-28 01:00'
+ time '01:00' + interval '3 hours' time '04:00'
- timestamp '2001-09-28 23:00' - interval '23 hours' timestamp '2001-09-28'
- date '2001-09-28' - interval '1 hour' timestamp '2001-09-27 23:00'
- time '05:00' - interval '2 hours' time '03:00'
- interval '2 hours' - time '05:00' time '03:00:00'
* interval '1 hour' * int '3' interval '03:00'
/ interval '1 hour' / int '3' interval '00:20'

表 6.18. 日期/时间函数

名称 返回类型 描述 示例 结果
age(timestamp) interval 从今天减去 age(timestamp '1957-06-13') 43 years 8 mons 3 days
age(timestamp, timestamp) interval 参数相减 age('2001-04-10', timestamp '1957-06-13') 43 years 9 mons 27 days
current_date date 今天的日期;见 第 6.8.4 节    
current_time time with time zone 当日的时刻;见 第 6.8.4 节    
current_timestamp timestamp with time zone 日期和时间;见第 6.8.4 节    
date_part(text, timestamp) double precision 获取子字段(等价于 extract);另见下文 date_part('hour', timestamp '2001-02-16 20:38:40') 20
date_part(text, interval) double precision 获取子字段(等价于 extract);另见下文 date_part('month', interval '2 years 3 months') 3
date_trunc(text, timestamp) timestamp 截断到指定精度;另见第 6.8.2 节 date_trunc('hour', timestamp '2001-02-16 20:38:40') 2001-02-16 20:00:00+00
extract(field from timestamp) double precision 获取子字段;另见第 6.8.1 节 extract(hour from timestamp '2001-02-16 20:38:40') 20
extract(field from interval) double precision 获取子字段;另见第 6.8.1 节 extract(month from interval '2 years 3 months') 3
isfinite(timestamp) boolean 测试时间戳是否有限(既非无效也非无穷) isfinite(timestamp '2001-02-16 21:28:30') true
isfinite(interval) boolean 测试时间间隔是否有限 isfinite(interval '4 hours') true
localtime time 当日的时刻;见 第 6.8.4 节    
localtimestamp timestamp 日期和时间;见第 6.8.4 节    
now() timestamp with time zone 当前的日期和时间(等效于current_timestamp);见第 6.8.4 节    
timeofday() text 当前的日期和时间;见 第 6.8.4 节 timeofday() Wed Feb 21 17:01:13.000126 2001 EST

6.8.1. EXTRACT, date_part #

EXTRACT (field FROM source)

extract 函数从日期/时间值中 检索诸如年或小时这样的子字段。 source 是一个求值结果为 timestamp 或 interval 类型的值表达式。 (date 或 time 类型的表达式 会被转换为 timestamp,因此也可以 使用。)field 是一个标识符或 字符串,它选择从源值中提取哪个字段。 extract 函数返回 double precision 类型的值。 下面是有效的取值:

century

年份字段除以 100

SELECT EXTRACT(CENTURY FROM TIMESTAMP '2001-02-16 20:38:40');
结果:20

注意,century 字段的结果只是年份字段 除以 100,而不是把 1900 年代的大部分年份 归入二十世纪的传统定义。

day

(月中的)日字段(1 - 31)

SELECT EXTRACT(DAY FROM TIMESTAMP '2001-02-16 20:38:40');
结果:16
decade

年份字段除以 10

SELECT EXTRACT(DECADE FROM TIMESTAMP '2001-02-16 20:38:40');
结果:200
dow

星期几(0 - 6;星期日为 0)(仅用于 timestamp 值)

SELECT EXTRACT(DOW FROM TIMESTAMP '2001-02-16 20:38:40');
结果:5
doy

一年中的第几天(1 - 365/366)(仅用于 timestamp 值)

SELECT EXTRACT(DOY FROM TIMESTAMP '2001-02-16 20:38:40');
结果:47
epoch

对于 date 和 timestamp 值,是自 1970-01-01 00:00:00-00 以来的秒数(可以为负); 对于 interval 值,是该间隔中的 总秒数

SELECT EXTRACT(EPOCH FROM TIMESTAMP '2001-02-16 20:38:40');
结果:982352320

SELECT EXTRACT(EPOCH FROM INTERVAL '5 days 3 hours');
结果:442800
hour

小时字段(0 - 23)

SELECT EXTRACT(HOUR FROM TIMESTAMP '2001-02-16 20:38:40');
结果:20
microseconds

秒字段(包括小数部分)乘以 1 000 000。注意这包括完整的秒数。

SELECT EXTRACT(MICROSECONDS FROM TIME '17:12:28.5');
结果:28500000
millennium

年份字段除以 1000

SELECT EXTRACT(MILLENNIUM FROM TIMESTAMP '2001-02-16 20:38:40');
结果:2

注意,millennium 字段的结果只是年份字段 除以 1000,而不是把 1900 年代的年份 归入第二个千年的传统定义。

milliseconds

秒字段(包括小数部分)乘以 1000。注意这包括完整的秒数。

SELECT EXTRACT(MILLISECONDS FROM TIME '17:12:28.5');
结果:28500
minute

分钟字段(0 - 59)

SELECT EXTRACT(MINUTE FROM TIMESTAMP '2001-02-16 20:38:40');
结果:38
month

对于 timestamp 值,是一年中的月份数 (1 - 12);对于 interval 值, 是月数模 12(0 - 11)

SELECT EXTRACT(MONTH FROM TIMESTAMP '2001-02-16 20:38:40');
结果:2

SELECT EXTRACT(MONTH FROM INTERVAL '2 years 3 months');
结果:3

SELECT EXTRACT(MONTH FROM INTERVAL '2 years 13 months');
结果:1
quarter

该日所在的一年中的季度(1 - 4)(仅用于 timestamp 值)

SELECT EXTRACT(QUARTER FROM TIMESTAMP '2001-02-16 20:38:40');
结果:1
second

秒字段(包括小数部分)(0 - 59[4])

SELECT EXTRACT(SECOND FROM TIMESTAMP '2001-02-16 20:38:40');
结果:40

SELECT EXTRACT(SECOND FROM TIME '17:12:28.5');
结果:28.5
timezone_hour

时区偏移量的小时部分。

timezone_minute

时区偏移量的分钟部分。

week

从 timestamp 值计算 该日所在一年中的 周数。根据定义 (ISO 8601),一年的第一周 包含该年的 1 月 4 日。(ISO 的周从星期一开始。)换句话说,一年的 第一个星期四在该年的第 1 周。

SELECT EXTRACT(WEEK FROM TIMESTAMP '2001-02-16 20:38:40');
结果:7
year

年份字段

SELECT EXTRACT(YEAR FROM TIMESTAMP '2001-02-16 20:38:40');
结果:2001

extract函数主要的用途是做计算性处理。对于用于显示的日期/时间值格式化,参阅第 6.7 节。

date_part 函数仿照传统 Ingres 中与 SQL 标准函数 extract 等价的函数建模:

date_part('field', source)

注意这里的 field 参数需要 是字符串值,而不是名称。date_part 的有效字段取值与 extract 的相同。

SELECT date_part('day', TIMESTAMP '2001-02-16 20:38:40');
结果:16

SELECT date_part('hour', INTERVAL '4 hours 3 minutes');
结果:4

6.8.2. date_trunc #

date_trunc函数在概念上和用于数字的trunc函数类似。

date_trunc('field', source)

source 是一个 timestamp 类型的值表达式(date 和 time 类型的值会被自动转换)。 field 选择把时间戳值 截断到哪种精度。返回值的类型是 timestamp,其中所有低于所选字段的字段 都被置为零(日和月则置为一)。

field 的有效值有:

microseconds
milliseconds
second
minute
hour
day
month
year
decade
century
millennium

例子:

SELECT date_trunc('hour', TIMESTAMP '2001-02-16 20:38:40');
结果:2001-02-16 20:00:00+00

SELECT date_trunc('year', TIMESTAMP '2001-02-16 20:38:40');
结果:2001-01-01 00:00:00+00

6.8.3. AT TIME ZONE #

AT TIME ZONE 结构允许把时间戳转换 到不同的时区。

表 6.19. AT TIME ZONE 变体

表达式 返回类型 描述
timestamp without time zone AT TIME ZONE zone timestamp with time zone 把给定时区中的本地时间转换为 UTC
timestamp with time zone AT TIME ZONE zone timestamp without time zone 把 UTC 转换为给定时区中的本地时间
time with time zone AT TIME ZONE zone time with time zone 跨时区转换本地时间

在这些表达式里,所需的时区 zone 既可以 指定为文本字符串(例如 'PST'), 也可以指定为一个间隔(例如 INTERVAL '-08:00')。

例子(假设 TimeZone 为 PST8PDT):

SELECT TIMESTAMP '2001-02-16 20:38:40' AT TIME ZONE 'MST';
结果:2001-02-16 19:38:40-08

SELECT TIMESTAMP WITH TIME ZONE '2001-02-16 20:38:40-05' AT TIME ZONE 'MST';
结果:2001-02-16 18:38:40

第一个例子取一个不带时区的时间戳并把它解释为 MST 时间 (GMT-7)以产生一个 UTC 时间戳,然后将其旋转为 PST(GMT-8) 用于显示。第二个例子取一个以 EST (GMT-5)指定的时间戳并把它转换为 MST(GMT-7)的本地时间。

函数 timezone(zone, timestamp) 等价于 SQL 兼容的结构 timestamp AT TIME ZONE zone。

6.8.4. 当前日期/时间 #

下列函数可用于获取当前日期和/或时间:

CURRENT_DATE
CURRENT_TIME
CURRENT_TIMESTAMP
CURRENT_TIME (precision)
CURRENT_TIMESTAMP (precision)
LOCALTIME
LOCALTIMESTAMP
LOCALTIME (precision)
LOCALTIMESTAMP (precision)

CURRENT_TIME和CURRENT_TIMESTAMP返回带时区的值;LOCALTIME和LOCALTIMESTAMP返回不带时区的值。

CURRENT_TIME、 CURRENT_TIMESTAMP、 LOCALTIME 和 LOCALTIMESTAMP 可以选择性地接受 一个精度参数,它使结果被舍入 到那么多位小数。如果没有精度参数, 结果将给出完整的可用精度。

注意

在PostgreSQL 7.2 之前,精度参数是没有实现的,结果总是以整数秒给出。

一些例子:

SELECT CURRENT_TIME;
14:39:53.662522-05

SELECT CURRENT_DATE;
2001-12-23

SELECT CURRENT_TIMESTAMP;
2001-12-23 14:39:53.662522-05

SELECT CURRENT_TIMESTAMP(2);
2001-12-23 14:39:53.66-05

SELECT LOCALTIMESTAMP;
2001-12-23 14:39:53.662522

now()是PostgreSQL中与CURRENT_TIMESTAMP等价的传统函数。

还有 timeofday(),由于历史 原因它返回一个文本字符串而不是 timestamp 值:

SELECT timeofday();
 Sat Feb 17 19:07:32.000126 2001 EST

重要的是要认识到 CURRENT_TIMESTAMP 及相关函数返回 当前事务的开始时间;它们的值在 事务期间不发生变化。timeofday() 返回墙上时钟时间并且在事务期间会前进。

注意

许多其他数据库系统更频繁地推进这些 值。

所有日期/时间数据类型也都接受特殊字面值now来指定当前日期和时间。因此,下面三种写法都返回相同的结果:

SELECT CURRENT_TIMESTAMP;
SELECT now();
SELECT TIMESTAMP 'now';

注意

在创建表时指定DEFAULT子句的情况下,你不希望使用第三种形式。 系统将在分析这个常量的时候把now转换为一个timestamp,这样需要默认值时就会得到创建表的时间!而前两种形式要到实际使用默认值的时候才被计算,因为它们是函数调用。因此它们可以给出每次插入行的时刻。



[4] 如果操作系统实现了闰秒则为 60

提交更正

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