4.7. 时间/日期函数

Table 4-14 显示了 Postgres 里可以用于处理日期/时间数值的函数.还有最基本的算术操作 (+* 等等). 而与格式化相关的函数,可以参考Section 4.6. 你应该很熟悉日期/时间数据类型的背景知识(Section 3.4).

Table 4-14. 日期/时间函数

函数返回描述例子结果
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_datedate今天的日期;见 下文   
current_timetime现在的时间;见下文   
current_timestamptimestamp日期和时间;又见下文   
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截断成指定的精度;又见下文 date_trunc('hour', timestamp '2001-02-16 20:38:40')2001-02-16 20:00:00+00
extract(field from timestamp)double precision获取子域;又见 下文 extract(hour from timestamp '2001-02-16 20:38:40')20
extract(field from interval)double precision获取子域;又见 下文 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
now()timestamp当前的日期和时间(等效于 current_timestamp);又见 下文   
timeofday()text高精度日期和时间;又见 下文 timeofday()Wed Feb 21 17:01:13.000126 2001 EST
timestamp(date)timestamp日期转换成 timestamptimestamp(date '2000-12-25')2000-12-25 00:00:00
timestamp(date, time)timestamp日期和时间转换成 timestamptimestamp(date '1998-02-24',time '23:07')1998-02-24 23:07:00

4.7.1. EXTRACTdate_part

EXTRACT (field FROM source)

extract 函数从日期/时间数值里抽取 子域,比如年或者小时等.source 是一个值表达式,可以计算出类型 timestamp 或者 interval.(类型为 date 或者 time 的表达式将转换为 timestamp 然后再处理.)field 是一个标识符 或者字串,它指定从源数据中抽取的数域.extract 函数返回类型为double precision 的数值. 下列数值是有效数值∶

世纪

年份域除以100

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

请注意,世纪数据域只是简单的年份域除以100,而不是传统的那样把 大多数19xx年放到二十世纪.

日期

(月分)里的日期域(1-31)

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

年代

年份域除以10

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

星期几(dow)

每周的星期号(0 - 6;星期天是 0) (仅用于 timestamp)

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

年日(doy)

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

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

纪元(epoch)

对于 datetimestamp 数值而言, 是自 1970-01-01 00:00:00 以来的秒数(结果可能是负数.); 对于 interval 数值而言,它是时间间隔的总秒数.

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

SELECT EXTRACT(EPOCH FROM INTERVAL '5 days 3 hours');
Result: 442800

小时(hour)

小时域 (0 - 23)

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

微秒(microseconds)

秒域,包括小数部分,乘以 1,000,000.请注意它包括全部的秒.

SELECT EXTRACT(MICROSECONDS FROM TIME '17:12:28.5');
Result: 28500000

千年(millennium)

年域除以 1000

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

请注意千年域只是简单的用 1000 除年域,而不是传统那样定义的 19xx 年是第二个千年.

毫秒(milliseconds)

秒域,包括小数部分,乘以 1000.请注意它包括完整的秒.

SELECT EXTRACT(MILLISECONDS FROM TIME '17:12:28.5');
Result: 28500

分钟(minute)

分钟域 (0 - 59)

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

月份(month)

对于 timestamp 数值,它是一年里的月份数(1 - 12); 对于 interval 数值,它是月的数目,然后对 12 取模(0 - 11)

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

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

SELECT EXTRACT(MONTH FROM INTERVAL '2 years 13 months');
Result: 1

季度(quarter)

该天所在的该年的季度(1 - 4)(仅用于 timestamp)

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

秒(second)

秒域,包括小数部分 (0 - 59 [1])

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

SELECT EXTRACT(SECOND FROM TIME '17:12:28.5');
Result: 28.5

周(week)

从一个 timestamp 数值里计算该天在所在的年份里 是第几周.根据定义 (ISO 8601),一年的 第一周包含该年的一月四日.(ISO 的周从星期一开始.) 换句话说,一年的第一个星期四在第一周.

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

年(year)

年份域

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

extract 函数主要的用途是做运算用. 对于用于显示的日期/时间数值格式化,参阅 Section 4.6

date_part 函数是在传统的 Ingres 函数的基础上制作的(该 函数等效于 SQL 函数 extract)∶

date_part('field', source)
请注意这里的 field 数值必须是 一个字串.有效的 date_part 数域数值 和用于 extract 的是一样的.

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

SELECT date_part('hour', INTERVAL '4 hours 3 minutes')
Result: 4

4.7.2. date_trunc

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

date_trunc('field', source)
source 是类型 timestamp 的值表达式(类型 datetime 的数值都自动转换). 用 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');
Result: 2001-02-16 20:00:00+00

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

4.7.3. 当前日期/时间

我们可以使用下面的函数获取当前的日期和/或时间∶

CURRENT_TIME
CURRENT_DATE
CURRENT_TIMESTAMP
请注意,因为 SQL 标准的要求, 这些函数后面不能有园括弧.

SELECT CURRENT_TIME;
19:07:32

SELECT CURRENT_DATE;
2001-02-17

SELECT CURRENT_TIMESTAMP;
2001-02-17 19:07:32-05

函数 now() 是传统的 PostgresCURRENT_TIMESTAMP 的等效物.

还有一个 timeofday() 函数,它返回比 CURRENT_TIMESTAMP 族函数更高精度的当前时间∶

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

timeofday() 使用操作系统调用 gettimeofday(2),它可能有高达 微秒的分辩率(具体情况取决于你的平台);其它依赖 time(2) 的函数的分辩率将局限于 一秒.由于历史原因,timeofday() 返回的结果是文本字串,而不是一个 timestamp 数值.

还有一件事提醒大家,那就是 CURRENT_TIMESTAMP 和相关的函数都把时间当做当前事务的开始返回;在事务运行的时候, 它们的数值并不增加.但 timeofday() 返回当前的实际时间.

所有日期/时间类型还接受特殊的文本值 now, 用于声明当前的日期和时间.因此,下面三个都返回相同的结果∶

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

注意: 在创建表声明一个 DEFAULT 值的时候你是不会想用第三种形式的. 因为系统将在分析这个常量的时候把 now 转换成 时间戳,因此在需要缺省值的时候,就会使用创建表的时间! 而头两种形式要到实际使用缺省值的时候才计算, 因为它们是函数调用.因此它们可以给出插入时间行的时候 需要的缺省行为.

Notes

[1]

如果操作系统实现了润秒, 那么上限是 60