操作符

例子

结果

+

date '2015-09-28' + integer '7'

date '20-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'

+

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 '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'

-

timestamp '2001-09-29 03:00' - timestamp '2001-09-27 12:00'

interval '1 day 15:00'

*

interval '1 hour' * double precision '3.5'

interval '03:30'

/

interval '1 hour' / double precision '1.5'

interval '00:40'


日期/时间函数

函数

返回类型

描述

例子

结果

age(timestamp,timestamp)

interval

减去参数,生成一个使用年、月的"符号化"的结果

age('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

current_date

date

今天的日期;见 Section 9.9.4

 

 

current_time

time with time zone

现在的时间;见 Section 9.9.4

 

 

current_timestamp

timestamp with time zone

日期和时间;见 Section 9.9.4

 

 

date_part(text,timestamp)

double precision

获取子域(等效于 extract);又见 Section 9.9.1

date_part('hour', timestamp '2001-02-16 20:38:40')

20

date_part(text,interval)

double precision

获取子域(等效于 extract);又见 Section 9.9.1

date_part('month', interval '2 years 3 months')

3

date_trunc(text,timestamp)

timestamp

截断成指定的精度;又见Section 9.9.2

date_trunc('hour', timestamp '2001-02-16 20:38:40')

2001-02-16 20:00:00+00

extract(field fromtimestamp)

double precision

获取子域;又见 Section 9.9.1

extract(hour from timestamp '2001-02-16 20:38:40')

20

extract(field frominterval)

double precision

获取子域;又见 Section 9.9.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

今日的时间;见 Section 9.9.4

 

 

localtimestamp

timestamp

日期和时间;见 Section 9.9.4

 

 

now()

timestamp with time zone

当前的日期和时间(等效于 current_timestamp);见Section 9.9.4

 

 

timeofday()

text

当前日期和时间;见Section 9.9.4

 

 

EXTRACT


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');
Result: 20
SELECT EXTRACT(CENTURY FROM TIMESTAMP '2001-02-16 20:38:40');
Result: 21

第一个世纪从 0001-01-01 00:00:00 AD 开始, 尽管那时候人们还不知道这是第一个世纪。这个定义适用于所有使用格里高利历法的国家。 没有 0 世纪,我们直接从公元前 1 世纪到公元 1 世纪。 如果你认为这个不合理,那么请把抱怨发给:罗马圣彼得教堂,梵蒂冈,教皇收。

PostgreSQL

day



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



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



年份域除以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


请注意 extract 的星期几编号和 to_char函数的不同。

doy



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



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



对于 date 和 timestamp 数值而言,是自 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



下面是把 epoch 值转换回时间戳的方法:



SELECT TIMESTAMP WITH TIME ZONE 'epoch' + 982384720 * INTERVAL '1 second';
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


千年。



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



20世纪(19xx年)里面的年份在第二个千年里。第三个千年从 2001 年一月一日开始。

PostgreSQL

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



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
timezone



与 UTC 的时区偏移,以秒记。正数对应 UTC 东边的时区,负数对应 UTC 西边的时区。

timezone_hour



时区偏移的小时部分。

timezone_minute



时区偏移的分钟部分。

week



该天在所在的年份里是第几周。根据定义 (ISO 8601),一年的第一周包含该年的一月四日。(ISO-8601的周从星期一开始。)换句话说,一年的第一个星期四在第一周。(只用于timestamp

因此,一月的头几天可能是前一年的第五十二或者第五十三周。比如,2005-01-01 是 2004 年的第五十三周,而2006-01-01



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

year



年份域。要记住这里没有 0 AD,所以从 AD 年里抽取BC



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


extract 函数主要的用途是做运算用。对于用于显示的日期/时间数值格式化,参阅Section 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'); Result: 16 SELECT date_part('hour', INTERVAL '4 hours 3 minutes'); Result: 4


9.9.2. date_trunc

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



date_trunc('field', source)



source 是类型timestamp 的值表达式(类型date 和 time 的数值都分别自动转换成timestamp或者interval)。用field 选择对该时间戳数值选用什么样的精度进行截断)。返回的数值是 timestamp 类型或者interval,所有小于选定的精度的域都设置为零(或者一,如果是日期和月份域的话)。

field

microseconds

milliseconds

second

minute

hour

day

week

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



9.9.3.AT TIME ZONE



AT TIME ZONE 构造允许把时间戳转换成不同的时区。Table 9-27 显示了其变体。



Table 9-27. AT TIME ZONE变体

表达式

返回类型

描述

timestamp without time zoneAT TIME ZONE zone

timestamp with time zone

把给出的不带时区的时间戳转换成指定时区的时间

timestamp with time zoneAT TIME ZONE zone

timestamp without time zone

把给出的带时区的时间转换为转换成给定时区的时间

time with time zoneAT TIME ZONE zone

time with time zone

在时区之间转换当地时间



在这些表达式里,我们需要的 zone 可以声明为文本串(比如,'PST')或者一个时间间隔(比如,INTERVAL '-08:00')。在文本的情况下,可用的时区名字要么在Table B-4要么在Table B-4 里面。

例子(假设本地时区是 PST8PDT):



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

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



第一个例子接受一个无时区的时间戳然后把她解释成 MST 时间(UTC-7)生成 UTC 时间戳,然后这个时间转换为 PST(UTC-8)来显示。第二个例子接受一个声明为 EST(UTC-5)的时间戳,然后把它转换成 MST(UTC-7)的当地时间。

函数timezone(zone,timestamp)等效于 SQL 兼容的构造timestampAT TIME ZONE zone


9.9.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



一些例子:



SELECT CURRENT_TIME;
Result: 14:39:53.662522-05

SELECT CURRENT_DATE;
Result: 2001-12-23

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

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

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


函数 now() 是传统的PostgreSQL 和CURRENT_TIMESTAMP

还有一件事提醒大家,那就是 CURRENT_TIMESTAMP 和相关的函数把时间当做当前事务的开始返回;在事务运行的时候,它们的数值并不改变。我们认为这是一个特性:目的是为了允许一个事务在"当前"时间上有连贯的概念,这样在同一个事务离得多个修改可以有同样的时间戳。



注意: 许多其它数据库系统更频繁地更新这些数值。



还有一个 timeofday() 函数,它返回实时的时间值,并且会在事务里随时间前进。由于历史原因,它返回一个text字串,而不是timestamp



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



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


SELECT CURRENT_TIMESTAMP;
SELECT now();
SELECT TIMESTAMP 'now'; -- 用在 DEFAULT 里是不正确的


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