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

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 10 已结束支持。 2022-11-10. 请参阅 当前版本手册.

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

表 9.30 展示了可用于处理日期/时间值的函数,其细节在随后的小节中描述。表 9.29 演示了基本算术操作符(+、* 等)的行为。而与格式化相关的函数,可以参考第 9.8 节。你应当熟悉第 8.5 节中的日期/时间数据类型的背景知识。

此外,表 9.1 中显示的常用比较操作符也适用于日期/时间类型。日期和时间戳(带或不带时区)都是可比较的,而时间(带或不带时区)和间隔只能与相同数据类型的其他值进行比较。将不带时区的时间戳与带时区的时间戳进行比较时,前者的值假定是在 TimeZone 配置参数指定的时区中给出的,并被转换到 UTC,以便与后者的值进行比较(后者在内部已用 UTC 表示)。类似地,日期值会被假定表示 TimeZone 区域中的午夜,当它与时间戳进行比较时。

所有下文描述的接受 time 或 timestamp 输入的函数和操作符实际上都有两种变体:一种接收 time with time zone 或 timestamp with time zone,另外一种接受 time without time zone 或者 timestamp without time zone。为了简化,这些变种没有被独立地展示。此外,+和* 操作符都是可交换的操作符对(例如,date + integer 和 integer + date);我们只显示每一对中的一个。

表 9.29. 日期/时间操作符

操作符示例结果
+ date '2001-09-28' + integer '7'date '2001-10-05'
+ date '2001-09-28' + interval '1 hour'timestamp '2001-09-28 01:00:00'
+ date '2001-09-28' + time '03:00'timestamp '2001-09-28 03:00:00'
+ interval '1 day' + interval '1 hour'interval '1 day 01:00:00'
+ timestamp '2001-09-28 01:00' + interval '23 hours'timestamp '2001-09-29 00:00:00'
+ time '01:00' + interval '3 hours'time '04:00:00'
-- interval '23 hours'interval '-23:00: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:00'
-time '05:00' - time '03:00'interval '02:00:00'
-time '05:00' - interval '2 hours'time '03:00:00'
-timestamp '2001-09-28 23:00' - interval '23 hours'timestamp '2001-09-28 00:00:00'
-interval '1 day' - interval '1 hour'interval '1 day -01:00:00'
-timestamp '2001-09-29 03:00' - timestamp '2001-09-27 12:00'interval '1 day 15:00:00'
* 900 * interval '1 second'interval '00:15:00'
* 21 * interval '1 day'interval '21 days'
* double precision '3.5' * interval '1 hour'interval '03:30:00'
/ interval '1 hour' / double precision '1.5'interval '00:40:00'

表 9.30. 日期/时间函数

函数返回类型描述示例结果
age(timestamp, timestamp)interval 将两个参数相减,生成一个使用年和月,而不是只用日的“符号化”的结果 age(timestamp '2001-04-10', timestamp '1957-06-13')43 years 9 mons 27 days
age(timestamp)interval从 current_date(午夜)减去age(timestamp '1957-06-13')43 years 8 mons 3 days
clock_timestamp()timestamp with time zone 当前日期和时间(在语句执行期间变化);参见第 9.9.4 节   
current_datedate 当前日期;参见第 9.9.4 节   
current_timetime with time zone一天中的当前时刻;参见第 9.9.4 节  
current_timestamptimestamp with time zone当前日期和时间(当前事务开始时);参见第 9.9.4 节  
date_part(text, timestamp)double precision获取子字段(等价于 extract);参见第 9.9.1 节date_part('hour', timestamp '2001-02-16 20:38:40')20
date_part(text, interval)double precision获取子字段(等价于 extract);参见第 9.9.1 节date_part('month', interval '2 years 3 months')3
date_trunc(text, timestamp)timestamp截断到指定精度;另见第 9.9.2 节date_trunc('hour', timestamp '2001-02-16 20:38:40')2001-02-16 20:00:00
date_trunc(text, interval)interval截断到指定精度;另见第 9.9.2 节date_trunc('hour', interval '2 days 3 hours 40 minutes')2 days 03:00:00
extract(field from timestamp)double precision获取子字段;参见第 9.9.1 节extract(hour from timestamp '2001-02-16 20:38:40')20
extract(field from interval)double precision获取子字段;参见第 9.9.1 节extract(month from interval '2 years 3 months')3
isfinite(date)boolean 测试日期是否有限(不是正负无穷) isfinite(date '2001-02-16')true
isfinite(timestamp)boolean测试时间戳是否有限(不是正负无穷)isfinite(timestamp '2001-02-16 21:28:30')true
isfinite(interval)boolean测试时间间隔是否有限isfinite(interval '4 hours')true
justify_days(interval)interval调整时间间隔,使 30 天的时段表示为月justify_days(interval '35 days')1 mon 5 days
justify_hours(interval)interval调整时间间隔,使 24 小时的时段表示为天justify_hours(interval '27 hours')1 day 03:00:00
justify_interval(interval)interval 使用 justify_days 和 justify_hours 调整时间间隔,并额外调整符号 justify_interval(interval '1 mon -1 hour')29 days 23:00:00
localtimetime一天中的当前时刻;参见第 9.9.4 节  
localtimestamptimestamp当前日期和时间(当前事务开始时);参见第 9.9.4 节  
make_date(year int, month int, day int) date 从年、月和日字段创建日期 make_date(2013, 7, 15)2013-07-15
make_interval(years int DEFAULT 0, months int DEFAULT 0, weeks int DEFAULT 0, days int DEFAULT 0, hours int DEFAULT 0, mins int DEFAULT 0, secs double precision DEFAULT 0.0) interval从年、月、周、日、小时、分钟和秒字段创建时间间隔make_interval(days => 10)10 days
make_time(hour int, min int, sec double precision) time 从小时、分钟和秒字段创建时间 make_time(8, 15, 23.5)08:15:23.5
make_timestamp(year int, month int, day int, hour int, min int, sec double precision) timestamp 从年、月、日、小时、分钟和秒字段创建时间戳 make_timestamp(2013, 7, 15, 8, 15, 23.5)2013-07-15 08:15:23.5
make_timestamptz(year int, month int, day int, hour int, min int, sec double precision, [ timezone text ]) timestamp with time zone从年、月、日、小时、分钟和秒字段创建带时区的时间戳;如果未指定 timezone,则使用当前时区。make_timestamptz(2013, 7, 15, 8, 15, 23.5)2013-07-15 08:15:23.5+01
now()timestamp with time zone当前日期和时间(当前事务开始时);参见第 9.9.4 节  
statement_timestamp()timestamp with time zone 当前日期和时间(当前语句开始时);参见第 9.9.4 节   
timeofday()text 当前的日期和时间(类似 clock_timestamp,但是采用 text 字符串);参见第 9.9.4 节   
transaction_timestamp()timestamp with time zone当前日期和时间(当前事务开始时);参见第 9.9.4 节  
to_timestamp(double precision)timestamp with time zone将 Unix 纪元时间(自 1970-01-01 00:00:00+00 起的秒数)转换为时间戳to_timestamp(1284352323)2010-09-13 04:32:03+00

除了这些函数以外,还支持 SQL 操作符 OVERLAPS:

(start1, end1) OVERLAPS (start2, end2)
(start1, length1) OVERLAPS (start2, length2)

这个表达式在两个时间段(用它们的端点定义)重叠的时候得到真,当它们不重叠时得到假。端点可以用一对日期、时间或者时间戳来指定;或者是用一个后面跟着一个间隔的日期、时间或时间戳来指定。当一对值被提供时,起点或终点都可以被写在前面,OVERLAPS 会自动地把较早的值作为起点。每一个时间段被认为是表示半开区间 start <= time < end,除非 start 和 end 相等,这种情况下它表示单个时刻。例如这表示两个只有一个共同端点的时间段不重叠。

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
SELECT (DATE '2001-10-29', DATE '2001-10-30') OVERLAPS
       (DATE '2001-10-30', DATE '2001-10-31');
结果:false
SELECT (DATE '2001-10-30', DATE '2001-10-30') OVERLAPS
       (DATE '2001-10-30', DATE '2001-10-31');
结果:true

当把一个 interval 值加到某个时间戳上(或从该时间戳中减去一个 interval 值)时,如果该时间戳为 timestamp with time zone 类型,天数部分会相应增加或减少 timestamp with time zone 的日期,变化天数为所指定的天数,而一天中的时刻保持不变。当跨越夏令时变化时(会话时区设为识别夏令时的时区),这意味着 interval '1 day' 不一定等于 interval '24 hours'。例如,当会话时区设置为 America/Denver:

SELECT timestamp with time zone '2005-04-02 12:00:00-07' + interval '1 day';
结果:2005-04-03 12:00:00-06
SELECT timestamp with time zone '2005-04-02 12:00:00-07' + interval '24 hours';
结果:2005-04-03 13:00:00-06

出现这种情况,是因为夏令时变化跳过了一个小时;变化发生的时间为 2005-04-03 02:00:00,所在时区为 America/Denver。

注意,age 返回的 months 字段可能存在歧义,因为不同月份的天数不同。PostgreSQL 在计算不足整月的部分时,会采用两个日期中较早的那个日期所在的月份。例如:age('2004-06-01', '2004-04-30') 使用 4 月得到 1 mon 1 day,而如果使用 5 月则会得到 1 mon 2 days,因为 5 月有 31 天,而 4 月只有 30 天。

日期和时间戳的减法也可能很复杂。一种概念上简单的方法是,先用 EXTRACT(EPOCH FROM ...) 将各值转换为秒数,然后将结果相减;这样得到的是两个值之间的秒数。这种方法会针对每个月的天数、时区变化和夏令时变化进行调整。用“-”操作符将日期或时间戳值相减,会返回两个值之间的天数(每一天为 24 小时)和时/分/秒,也会作相同的调整。age 函数返回年、月、日和时/分/秒,它会逐字段相减,然后调整负值字段。以下查询显示了这些方法的差异。示例结果在 timezone = 'US/Eastern' 设置下产生;所用的两个日期之间发生了夏令时切换:

SELECT EXTRACT(EPOCH FROM timestamptz '2013-07-01 12:00:00') -
       EXTRACT(EPOCH FROM timestamptz '2013-03-01 12:00:00');
结果:10537200
SELECT (EXTRACT(EPOCH FROM timestamptz '2013-07-01 12:00:00') -
        EXTRACT(EPOCH FROM timestamptz '2013-03-01 12:00:00'))
        / 60 / 60 / 24;
结果:121.958333333333
SELECT timestamptz '2013-07-01 12:00:00' - timestamptz '2013-03-01 12:00:00';
结果:121 days 23:00:00
SELECT age(timestamptz '2013-07-01 12:00:00', timestamptz '2013-03-01 12:00:00');
结果:4 mons

9.9.1. EXTRACT, date_part #

EXTRACT(field FROM source)

该 extract 函数从日期/时间值中提取年份、小时等子字段。source 必须是以下类型的值表达式:timestamp,time,或 interval。(date 类型的表达式会转换为 timestamp,因此也可以使用。)field 是一个标识符或字符串,用于选择从源值中提取的字段。extract 函数返回的值的类型为 double precision。以下是有效的字段名称:

century

世纪

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

第一个世纪始于公元 0001-01-01 00:00:00,尽管当时的人们并不知道。这一定义适用于所有采用格里高利历的国家。世纪编号没有 0,而是从 -1 世纪直接跳到 1 世纪。如果你对此有异议,请向梵蒂冈罗马圣彼得大教堂的教皇投诉。

day

对于 timestamp 值,表示月份中的日期字段(1 - 31);对于 interval 值,表示天数

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

年份字段除以 10

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

一周的日子从星期天(0)到星期六(6)

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

请注意 extract 函数的星期几编号与 to_char(..., 'D') 函数不同。

doy

一年中的第几天(1 - 365/366)

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

对于 timestamp with time zone 值,自 1970-01-01 00:00:00 UTC 以来的秒数(早于该时刻的时间戳对应负值);对于 date 和 timestamp 值,自 1970-01-01 00:00:00 以来的名义秒数,不考虑时区或夏令时规则;对于 interval 值,间隔中的总秒数

SELECT EXTRACT(EPOCH FROM TIMESTAMP WITH TIME ZONE '2001-02-16 20:38:40.12-08');
结果:982384720.12
SELECT EXTRACT(EPOCH FROM TIMESTAMP '2001-02-16 20:38:40.12');
结果:982355920.12
SELECT EXTRACT(EPOCH FROM INTERVAL '5 days 3 hours');
结果:442800

您可以使用 to_timestamp 将一个 epoch 值转换回 timestamp with time zone:

SELECT to_timestamp(982384720.12);
结果:2001-02-17 04:38:40.12+00

注意,将 to_timestamp 应用于从 date 或 timestamp 值中提取的 epoch 值可能会产生误导性的结果:结果实际上会假定原始值是以 UTC 时间给出的,这可能并非事实。

hour

小时字段(0 - 23)

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

一周的日子从星期一(1)到星期日(7)

SELECT EXTRACT(ISODOW FROM TIMESTAMP '2001-02-18 20:38:40');
结果:7

这与 dow 相同,除了星期天。这匹配 ISO 8601 的星期几编号。

isoyear

日期所属的 ISO 8601 周编号年份(不适用于间隔)

SELECT EXTRACT(ISOYEAR FROM DATE '2006-01-01');
结果:2005
SELECT EXTRACT(ISOYEAR FROM DATE '2006-01-02');
结果:2006

每个 ISO 8601 周编号年都从包含 1 月 4 日的那一周的星期一开始,因此在 1 月初或 12 月末,ISO 年可能与格里高利年不同。更多信息请参见 week 字段。

PostgreSQL 8.3 之前的版本不支持此字段。

julian

与日期或时间戳对应的儒略日(不适用于间隔)。非本地午夜的时间戳会产生带小数部分的值。更多信息请参见第 B.7 节。

SELECT EXTRACT(JULIAN FROM DATE '2006-01-01');
结果:2453737
SELECT EXTRACT(JULIAN FROM TIMESTAMP '2006-01-01 12:00');
结果:2453737.5
microseconds

秒字段,包括小数部分,乘以 1 000 000;注意这包括完整的秒数

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

千年

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

1900 年代的年份属于第二个千年。第三个千年始于 2001 年 1 月 1 日。

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)

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

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

SELECT EXTRACT(SECOND FROM TIMESTAMP '2001-02-16 20:38:40');
结果:40
SELECT EXTRACT(SECOND FROM TIME '17:12:28.5');
结果:28.5
timezone

与 UTC 的时区偏移量,以秒为单位。正值对应于 UTC 东部的时区,负值对应于 UTC 西部的时区。(从技术上讲,PostgreSQL 不使用 UTC,因为不处理闰秒。)

timezone_hour

时区偏移的小时部分

timezone_minute

时区偏移的分钟部分

week

一年中按 ISO 8601 周编号体系计算的周序号。根据定义,ISO 周从周一开始,一年的第一周包含该年的 1 月 4 日。换句话说,一年的第一个星期四在该年的第 1 周。

在 ISO 周编号体系中,1 月初的日期可能属于前一年的第 52 周或第 53 周,而 12 月末的日期可能属于下一年的第一周。例如,2005-01-01 属于 2004 年的第 53 周,2006-01-01 属于 2005 年的第 52 周,而 2012-12-31 属于 2013 年的第一周。建议将 isoyear 字段与 week 一起使用,以获得一致的结果。

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

年份字段。请记住,没有 0 AD,所以把 BC 年份从 AD 年份中减去时需要小心。

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

注意

当输入值为 +/-Infinity 时,extract 对于单调递增的字段(epoch、julian、year、isoyear、decade、century 以及 millennium)返回 +/-Infinity。对于其他字段返回 NULL。PostgreSQL 9.6 之前的版本对所有输入无穷的情况都返回零。

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

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

9.9.2. 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
week
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

9.9.3. AT TIME ZONE #

AT TIME ZONE 可在不带时区和带时区的时间戳之间相互转换,也可将时间值转换到不同的时区。表 9.31 展示了它的各种变体。

表 9.31. AT TIME ZONE 变体

表达式返回类型描述
timestamp without time zone AT TIME ZONE zonetimestamp with time zone将给定的不带时区时间戳视为指定时区中的时间
timestamp with time zone AT TIME ZONE zonetimestamp without time zone将给定的带时区时间戳转换为新时区的时间,结果不带时区标识
time with time zone AT TIME ZONE zonetime with time zone将给定的带时区时间转换为新时区的时间

在这些表达式里,所需的时区 zone 可以指定为文本值(例如 'America/Los_Angeles'),也可以指定为一个间隔值(例如 INTERVAL '-08:00')。在文本情况下,时区名称可以按第 8.5.3 节中描述的任意方式指定。

示例(假设本地时区为 America/Los_Angeles):

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

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

SELECT TIMESTAMP '2001-02-16 20:38:40-05' AT TIME ZONE 'Asia/Tokyo' AT TIME ZONE 'America/Chicago';
结果:2001-02-16 05:38:40

第一个示例为不带时区的值添加时区,并使用当前 TimeZone 设置显示该值。第二个示例将带时区的时间戳值移到指定时区,并返回不带时区的值。这样就可以存储和显示与当前 TimeZone 设置不同的值。第三个示例将东京时间转换为芝加哥时间。将 time 值转换到其他时区时,由于没有提供日期,会使用当前生效的时区规则。

函数 timezone(zone, timestamp) 等效于符合 SQL 标准的结构 timestamp AT TIME ZONE zone。

9.9.4. 当前日期/时间 #

PostgreSQL 提供了许多返回当前日期和时间的函数。这些 SQL 标准的函数全部都按照当前事务的开始时刻返回值:

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 可以有选择地接受一个精度参数,该精度会使结果的秒字段舍入到指定的小数位数。如果没有精度参数,结果将给出可用的全部精度。

一些示例:

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

因为这些函数全部都按照当前事务的开始时刻返回结果,所以它们的值在事务运行的整个期间内都不改变。我们认为这是一个特性:目的是为了允许一个事务在“当前”时间上有一致的概念,这样在同一个事务里的多个修改可以保持同样的时间戳。

注意

其他数据库系统可能会更频繁地推进这些值。

PostgreSQL 还提供了返回当前语句的开始时间以及调用该函数时的实际当前时间的函数。这些非 SQL 标准的函数列表如下:

transaction_timestamp()
statement_timestamp()
clock_timestamp()
timeofday()
now()

transaction_timestamp() 等价于 CURRENT_TIMESTAMP,但是其命名清楚地反映了它的返回值。statement_timestamp() 返回当前语句的开始时刻(更准确地说,是接收到客户端最近一条命令消息的时间)。statement_timestamp() 和 transaction_timestamp() 在一个事务的第一条命令期间返回值相同,但是在随后的命令中却不一定相同。clock_timestamp() 返回真正的当前时间,因此它的值甚至在同一条 SQL 命令中都会变化。timeofday() 是一个有历史原因的 PostgreSQL 函数。和 clock_timestamp() 相似,它也返回真实的当前时间,但是它的结果是一个格式化的 text 串,而不是 timestamp with time zone 值。now() 是 PostgreSQL 中与 transaction_timestamp() 等价的传统函数。

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

SELECT CURRENT_TIMESTAMP;
SELECT now();
SELECT TIMESTAMP 'now';  -- 但请参阅下面的提示

提示

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

9.9.5. 延时执行 #

以下函数可用于延迟服务器进程的执行:

pg_sleep(seconds)
pg_sleep_for(interval)
pg_sleep_until(timestamp with time zone)

pg_sleep 使当前会话的进程休眠 seconds 秒。seconds 的类型为 double precision,因此可以指定带小数部分的秒数作为延迟时间。pg_sleep_for 便于指定较长的休眠时间,其参数类型为 interval。pg_sleep_until 是在需要指定唤醒时间时使用的便利函数。例如:

SELECT pg_sleep(1.5);
SELECT pg_sleep_for('5 minutes');
SELECT pg_sleep_until('tomorrow 03:00');

注意

有效的休眠时间间隔精度与平台有关,0.01 秒是常见值。休眠延迟将至少持续指定的时长,也有可能由于服务器负荷而比指定的时间长。特别地,pg_sleep_until 并不保证能刚好在指定的时刻被唤醒,但它不会在比指定时刻早的时候醒来。

警告

请确保在调用 pg_sleep 或者其变体时,你的会话没有持有不必要的锁。否则其它会话可能必须等待你的休眠会话,因而减慢整个系统速度。



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

报告文档问题

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