pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。
表 9.26展示了可用于处理日期/时间值的函数,其细节在随后的小节中描述。表 9.25演示了基本算术操作符 (+、*等)的行为。 而与格式化相关的函数,可以参考第 9.7 节。你应当熟悉第 8.5 节中的日期/时间数据类型的背景知识。
下文描述的所有接受 time 或 timestamp 输入的函数和操作符实际上都有两个变体:一个接受 time with time zone 或 timestamp with time zone,另一个接受 time without time zone 或 timestamp without time zone。 为简洁起见,这些变体没有单独列出。
表 9.25. 日期/时间操作符
| 操作符 | 示例 | 结果 |
|---|---|---|
+ |
date '2001-09-28' + integer '7' |
date '2001-10-05' |
+ |
date '2001-09-28' + interval '1 hour' |
timestamp '2001-09-28 01:00' |
+ |
date '2001-09-28' + time '03:00' |
timestamp '2001-09-28 03:00' |
+ |
time '03:00' + date '2001-09-28' |
timestamp '2001-09-28 03:00' |
+ |
interval '1 day' + interval '1 hour' |
interval '1 day 01:00' |
+ |
timestamp '2001-09-28 01:00' + interval '23 hours' |
timestamp '2001-09-29 00:00' |
+ |
time '01:00' + interval '3 hours' |
time '04:00' |
+ |
interval '3 hours' + time '01:00' |
time '04:00' |
- |
- interval '23 hours' |
interval '-23:00' |
- |
date '2001-10-01' - date '2001-09-28' |
integer '3' |
- |
date '2001-10-01' - integer '7' |
date '2001-09-24' |
- |
date '2001-09-28' - interval '1 hour' |
timestamp '2001-09-27 23:00' |
- |
time '05:00' - time '03:00' |
interval '02:00' |
- |
time '05:00' - interval '2 hours' |
time '03:00' |
- |
timestamp '2001-09-28 23:00' - interval '23 hours' |
timestamp '2001-09-28 00:00' |
- |
interval '1 day' - interval '1 hour' |
interval '23:00' |
- |
interval '2 hours' - time '05:00' |
time '03:00' |
- |
timestamp '2001-09-29 03:00' - timestamp '2001-09-27 12:00' |
interval '1 day 15:00' |
* |
double precision '3.5' * interval '1 hour' |
interval '03:30' |
* |
interval '1 hour' * double precision '3.5' |
interval '03:30' |
/ |
interval '1 hour' / double precision '1.5' |
interval '00:40' |
表 9.26. 日期/时间函数
| 函数 | 返回类型 | 描述 | 示例 | 结果 |
|---|---|---|---|---|
|
interval |
从今天减去 | age(timestamp '1957-06-13') |
43 years 8 mons 3 days |
|
interval |
参数相减 | age('2001-04-10', timestamp '1957-06-13') |
43 years 9 mons 27 days |
|
date |
今天的日期;见 第 9.8.4 节 | ||
|
time with time zone |
当日的时刻;见 第 9.8.4 节 | ||
|
timestamp with time zone |
日期和时间;见第 9.8.4 节 | ||
|
double precision |
获取子字段(等价于 extract);参见第 9.8.1 节 |
date_part('hour', timestamp '2001-02-16 20:38:40') |
20 |
|
double precision |
获取子字段(等价于 extract);参见第 9.8.1 节 |
date_part('month', interval '2 years 3 months') |
3 |
|
timestamp |
截断到指定精度;另见第 9.8.2 节 | date_trunc('hour', timestamp '2001-02-16 20:38:40') |
2001-02-16 20:00:00 |
|
double precision |
获取子字段;参见第 9.8.1 节 | extract(hour from timestamp '2001-02-16 20:38:40') |
20 |
|
double precision |
获取子字段;参见第 9.8.1 节 | extract(month from interval '2 years 3 months') |
3 |
|
boolean |
测试时间戳是否有限(不等于无穷) | isfinite(timestamp '2001-02-16 21:28:30') |
true |
|
boolean |
测试时间间隔是否有限 | isfinite(interval '4 hours') |
true |
|
time |
当日的时刻;见 第 9.8.4 节 | ||
|
timestamp |
日期和时间;见第 9.8.4 节 | ||
|
timestamp with time zone |
当前的日期和时间(等效于current_timestamp);见第 9.8.4 节 |
||
|
text |
当前的日期和时间;见 第 9.8.4 节 |
除了这些函数之外,还支持 SQL 的 OVERLAPS 操作符:
(start1,end1) OVERLAPS (start2,end2) (start1,length1) OVERLAPS (start2,length2)
当两个时间段(由其端点定义)重叠时,该表达式产生真; 不重叠时产生假。端点 可以指定为一对日期、时间或时间戳;也可以是一个 日期、时间或时间戳后跟一个时间间隔。
SELECT (DATE '2001-02-16', DATE '2001-12-21') OVERLAPS
(DATE '2001-10-30', DATE '2002-10-30');
结果:true
SELECT (DATE '2001-02-16', INTERVAL '100 days') OVERLAPS
(DATE '2001-10-30', DATE '2002-10-30');
结果:false
EXTRACT, date_part #EXTRACT (fieldFROMsource)
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 WITH TIME ZONE '2001-02-16 20:38:40-08'); 结果:982384720SELECT 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'); 结果:2SELECT EXTRACT(MONTH FROM INTERVAL '2 years 3 months'); 结果:3SELECT 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[3])
SELECT EXTRACT(SECOND FROM TIMESTAMP '2001-02-16 20:38:40'); 结果:40SELECT EXTRACT(SECOND FROM TIME '17:12:28.5'); 结果:28.5
timezone相对 UTC 的时区偏移量,以秒为单位。正值 对应 UTC 以东的时区,负值对应 UTC 以西的时区。
timezone_hour时区偏移量的小时部分
timezone_minute时区偏移量的分钟部分
week该日所在一年中的 周数。根据定义 (ISO 8601),一年的第一周 包含该年的 1 月 4 日。(ISO-8601 的周从星期一开始。)换句话说,一年的 第一个星期四在该年的第 1 周。(仅用于 timestamp 值)
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函数主要的用途是做计算性处理。对于用于显示的日期/时间值格式化,参阅第 9.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
date_trunc #date_trunc函数在概念上和用于数字的trunc函数类似。
date_trunc('field', source)
source是timestamp或interval类型的值表达式。(类型为date和time的值会自动转换为timestamp或interval,分别对应这两种输入类型。)field选择输入值的截断精度。返回值的类型是timestamp或interval,所有小于所选精度的字段都设为零(日和月则设为一)。
field 的有效值有:
microseconds |
milliseconds |
second |
minute |
hour |
day |
month |
quarter |
year |
decade |
century |
millennium |
示例:
SELECT date_trunc('hour', TIMESTAMP '2001-02-16 20:38:40');
结果:2001-02-16 20:00:00
SELECT date_trunc('year', TIMESTAMP '2001-02-16 20:38:40');
结果:2001-01-01 00:00:00
AT TIME ZONE #AT TIME ZONE结构允许把时间戳转换到不同的时区。表 9.27展示了它的各种变体。
表 9.27. AT TIME ZONE 变体
| 表达式 | 返回类型 | 描述 |
|---|---|---|
|
timestamp with time zone |
把给定时区中的本地时间转换为 UTC |
|
timestamp without time zone |
把 UTC 转换为给定时区中的本地时间 |
|
time with time zone |
跨时区转换本地时间 |
在这些表达式里,所需的时区 zone 既可以 指定为文本字符串(例如 'PST'), 也可以指定为一个间隔(例如 INTERVAL '-08:00')。
示例(假定本地时区为PST8PDT):
SELECT TIMESTAMP '2001-02-16 20:38:40' AT TIME ZONE 'MST'; 结果:2001-02-16 19:38:40-08SELECT TIMESTAMP WITH TIME ZONE '2001-02-16 20:38:40-05' AT TIME ZONE 'MST'; 结果:2001-02-16 18:38:40
第一个示例取一个无时区的时间戳,把它解释为 MST 时间(UTC-7)以产生一个 UTC 时间戳,然后旋转到 PST(UTC-8)显示。第二个示例取一个以 EST(UTC-5)指定的时间戳,把它转换成 MST(UTC-7)的本地时间。
函数等效于符合 SQL 标准的结构timezone(zone, timestamp)。timestamp AT TIME ZONE zone
下列函数可用于获取当前日期和/或时间:
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-05SELECT CURRENT_DATE; 结果:2001-12-23SELECT CURRENT_TIMESTAMP; 结果:2001-12-23 14:39:53.662522-05SELECT CURRENT_TIMESTAMP(2); 结果:2001-12-23 14:39:53.66-05SELECT LOCALTIMESTAMP; 结果:2001-12-23 14:39:53.662522
now()是PostgreSQL中与CURRENT_TIMESTAMP等价的传统函数。
还有函数timeofday(),出于历史原因,它返回一个text字符串而不是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,这样需要默认值时就会得到创建表的时间!而前两种形式要到实际使用默认值的时候才被计算,因为它们是函数调用。因此它们可以给出每次插入行的时刻。
译文有误、术语不当或页面显示问题,请到译文仓库 pgsty/pgdoc 报告译文问题。 英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。