跳转至

时间/日期函数和操作符

时间/日期函数和操作符

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

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

日期/时间操作符

+
操作符
+
描述
日期或时间相加
示例

``` sql seaboxsql=# select date '2001-09-28' + integer '7'; ?column?


2001-10-05 (1 row)

seaboxsql=# select date '2001-09-28' + time '03:00'; ?column?


2001-09-28 03:00:00 (1 row)

seaboxsql=# select interval '1 day' + interval '1 hour'; ?column?


1 day 01:00:00 (1 row)

seaboxsql=# select timestamp '2001-09-28 01:00' + interval '23 hours'; ?column?


2001-09-29 00:00:00 (1 row)

seaboxsql=# select time '01:00' + interval '3 hours'; ?column?


04:00:00 (1 row) ```

-
操作符
-
描述
日期或时间相加
示例

``` sql seaboxsql=# select - interval '23 hours'; ?column?


-23:00:00 (1 row)

seaboxsql=# select date '2001-10-01' - date '2001-09-28'; ?column?


3 (1 row)

seaboxsql=# select date '2001-10-01' - integer '7'; ?column?


2001-09-24 (1 row)

seaboxsql=# select date '2001-09-28' - interval '1 hour'; ?column?


2001-09-27 23:00:00 (1 row)

seaboxsql=# select time '05:00' - time '03:00'; ?column?


02:00:00 (1 row)

seaboxsql=# select time '05:00' - interval '2 hours'; ?column?


03:00:00 (1 row)

seaboxsql=# select timestamp '2001-09-28 23:00' - interval '23 hours'; ?column?


2001-09-28 00:00:00 (1 row)

seaboxsql=# select interval '1 day' - interval '1 hour'; ?column?


1 day -01:00:00 (1 row)

seaboxsql=# select timestamp '2001-09-29 03:00' - timestamp '2001-09-27 12:00'; ?column?


1 day 15:00:00 (1 row) ```

*
操作符
*
描述
日期间隔的倍数
示例

``` sql seaboxsql=# select 900 * interval '1 second'; ?column?


00:15:00 (1 row)

seaboxsql=# select 21 * interval '1 day'; ?column?


21 days (1 row)

seaboxsql=# select double precision '3.5' * interval '1 hour'; ?column?


03:30:00 (1 row) ```

/
操作符
/
描述
日期间隔的倍数
示例

``` sql seaboxsql=# select interval '1 hour' / double precision '1.5'; ?column?


00:40:00 (1 row)

seaboxsql=# select interval '1 hour' / interval '20 second'; ?column?


180 (1 row) ```

日期/时间函数

age()
语法
age(timestamp[, timestamp])
返回类型
interval
描述
减去参数,生成一个使用年、月(而不是只用日)的“符号化”的结果; 参数仅一个时表示参数日期与current_date(在午夜)的差值
示例

``` sql seaboxsql=# select age(timestamp '2001-04-10', timestamp '1957-06-13'); age


43 years 9 mons 27 days (1 row)

seaboxsql=# select age(timestamp '1957-06-13'); age


64 years 7 mons 11 days (1 row) ```

clock_timestamp()
语法
clock_timestamp()
返回类型
timestamp with time zone
描述
当前日期和时间(在语句执行期间变化);见 当前日期/时间
current_date()
语法
current_date
返回类型
date
描述
当前日期;见 当前日期/时间
current_time()
语法
current_time
返回类型
time with time zone
描述
当前时间(一天中的时间);见 当前日期/时间
current_timestamp()
语法
current_timestamp
返回类型
timestamp with time zone
描述
当前日期和时间(当前事务开始时);见 当前日期/时间
date_part()
语法
date_part(text, [timestamp|interval])
返回类型
double precision
描述
获得子域(等价于extract);见 EXTRACT,date_part
示例

``` sql seaboxsql=# select date_part('hour', timestamp '2001-02-16 20:38:40'); date_part


20

(1 row)

seaboxsql=# select date_part('month', interval '2 years 3 months'); date_part


    3

(1 row) ```

date_trunc()
语法
date_trunc(text,[timestamp|interval])
返回类型
[timestamp|interval]
描述
截断到指定精度;另见 date_trunc
示例

``` sql seaboxsql=# select date_trunc('hour', timestamp '2001-02-16 20:38:40'); date_trunc


2001-2-16 20:00 (1 row)

seaboxsql=# select date_trunc('hour', interval '2 days 3 hours 40 minutes'); date_trunc


2 days 03:00:00 (1 row) ```

extract()
语法
extract(field from [timestamp|interval])
返回类型
double precision
描述
获得子域;见 EXTRACT,date_part
示例

``` sql seaboxsql=# select extract(hour from timestamp '2001-02-16 20:38:40'); date_part


20

(1 row)

seaboxsql=# select extract(month from interval '2 years 3 months'); date_part


    3

(1 row) ```

isfinite()
语法
isfinite([date|timestamp|interval])
返回类型
boolean
描述
测试有限日期(不是±无限)或有限间隔
示例

``` sql seaboxsql=# select isfinite(date '2001-02-16'); isfinite


t (1 row)

seaboxsql=# select isfinite(timestamp '2001-02-16 21:28:30'); isfinite


t (1 row)

seaboxsql=# select isfinite(interval '4 hours'); isfinite


t (1 row) ```

justify_days()
语法
justify_days(interval)
返回类型
interval
描述
调整间隔这样30天时间周期可以表示为月
示例
``` sql seaboxsql=# select justify_days(interval '35 days'); justify_days
1 mon 5 days (1 row) ```
justify_hours()
语法
justify_hours(interval)
返回类型
interval
描述
调整间隔这样24小时时间周期可以表示为日
示例
``` sql seaboxsql=# select justify_hours(interval '27 hours'); justify_hours
1 day 03:00:00 (1 row) ```
justify_interval()
语法
justify_interval(interval)
返回类型
interval
描述
使用justify_days和justify_hours调整间隔,使用额外的符号调整
示例
``` sql seaboxsql=# select justify_interval(interval '1 mon -1 hour'); justify_interval
29 days 23:00:00 (1 row) ```
localtime()
语法
localtime
返回类型
time
描述
当前时间(一天中的时间);见 当前日期/时间
localtimestamp()
语法
localtimestamp
返回类型
timestamp
描述
当前日期和时间(当前事务的开始);见 当前日期/时间
make_date()
语法
make_date(year int, month int, day int)
返回类型
date
描述
从年、月、日域创建日期
示例
``` sql seaboxsql=# select make_date(2013, 7, 15); make_date
2013/7/15 (1 row) ```
make_interval()
语法
make_interval(years int DEFAULT 0, 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
描述
从年、月、周、日、时、分、秒域创建 interval
示例

``` sql seaboxsql=# select make_interval(days => 10); make_interval


10 days

(1 row) ```

make_time()
语法
make_time(hour int, min int, sec double precision)
返回类型
time
描述
从时、分、秒域创建时间
示例
``` sql seaboxsql=# select make_time(8, 15, 23.5); make_time
08:15:23.5 (1 row) ```
make_timestamp()
语法
make_timestamp(years int, months int, days int,hour int, min int, sec double precision)
返回类型
timestamp
描述
从年、月、日、时、分、秒域创建时间戳
示例
``` sql seaboxsql=# select make_timestamp(2013, 7, 15, 8, 15, 23.5); make_timestamp
2013-07-15 08:15:23.5 (1 row) ```
make_timestamptz()
语法
make_timestamptz(years int, months int,days int, hour int, min int, sec double precision, [timezone text])
返回类型
timestamp with time zone
描述
从年、月、日、时、分、秒域创建带时区的时间戳。如果没有指定timezone, 则使用当前时区。
示例
``` sql seaboxsql=# select make_timestamptz(2013, 7, 15, 8, 15, 23.5); make_timestamptz
2013-07-15 08:15:23.5+08 (1 row) ```
now()
语法
now()
返回类型
timestamp with time zone
描述
当前日期和时间(当前事务的开始);见 当前日期/时间
statement_timestamp()
语法
statement_timestamp()
返回类型
timestamp with time zone
描述
当前日期和时间(当前事务的开始);见 当前日期/时间
timeofday()
语法
timeofday()
返回类型
text
描述
当前日期和时间(像clock_timestamp,但是作为一个text字符串)
transaction_timestamp()
语法
transaction_timestamp()
返回类型
timestamp with time zone
描述
当前日期和时间(当前事务的开始);见 当前日期/时间
to_timestamp()
语法
to_timestamp(double precision)
返回类型
timestamp with time zone
描述
把 Unix 时间(从 1970-01-01 00:00:00+00 开始的秒)转换成 timestamp
示例
``` sql seaboxsql=# select to_timestamp(1284352323); to_timestamp
2010-09-13 12:32:03+08 (1 row) ```
QL操作符OVERLAPS
语法
sql (start1, end1) OVERLAPS (start2, end2) (start1, length1) OVERLAPS (start2, length2)
描述
这个表达式在两个时间域(用它们的端点定义)重叠的时候得到真,当它们不重叠时得到假。端点可以用一对日期、时间或者时间戳来指定;或者是用一个后面跟着一个间隔的日期、时间或时间戳来指定。当一对值被提供时,起点或终点都可以被写在前面,OVERLAPS会自动地把较早的值作为起点。每一个时间段被认为是表示半开的间隔 start<= time <end,除非 startend 相等,这种情况下它表示单个时间实例。例如这表示两个只有一个共同端点的时间段不重叠。
示例

``` sql seaboxsql=# SELECT (DATE '2001-02-16', DATE '2001-12-21') OVERLAPS seaboxsql-# (DATE '2001-10-30', DATE '2002-10-30'); overlaps


t (1 row)

seaboxsql=# SELECT (DATE '2001-02-16', INTERVAL '100 days') OVERLAPS seaboxsql-# (DATE '2001-10-30', DATE '2002-10-30'); overlaps


f (1 row)

seaboxsql=# SELECT (DATE '2001-10-29', DATE '2001-10-30') OVERLAPS seaboxsql-# (DATE '2001-10-30', DATE '2001-10-31'); overlaps


f (1 row)

seaboxsql=# SELECT (DATE '2001-10-30', DATE '2001-10-30') OVERLAPS seaboxsql-# (DATE '2001-10-30', DATE '2001-10-31'); overlaps


t (1 row) ```

夏令时说明

当把一个interval值添加到timestamp with time zone上(或从中减去)时, days部分会按照指定的天数增加或减少timestamp with time zone的日期。对于横跨夏令时的变化(当会话的时区被设置为可识别DST的时区时),这意味着interval '1 day'并不一定等于interval '24 hours'。例如,当会话的时区设置为CST7CDT时,timestamp with time zone '2005-04-02 12:00-07' + interval '1 day'的结果是timestamp with time zone '2005-04-03 12:00-06',而将interval '24 hours'增加到相同的初始timestamp with time zone的结果则是timestamp with time zone '2005-04-03 13:00-06',因为CST7CDT时区在2005-04-03 02:00有一个夏令时变更。

注意age返回的月数域可能有歧义,因为不同的月份有不同的天数。SeaboxSQL的方法是当计算部分月数时,采用两个日期中较早的月。例如: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'产生,这使得两个使用的日期之间存在着夏令 时的变化.

示例

``` sql seaboxsql=# SELECT EXTRACT(EPOCH FROM timestamptz '2013-03-01 12:00:00'); date_part


10540800 (1 row)

seaboxsql=# SELECT (EXTRACT(EPOCH FROM timestamptz '2013-07-01 12:00:00') - seaboxsql(# EXTRACT(EPOCH FROM timestamptz '2013-03-01 12:00:00')) seaboxsql-# / 60 / 60 / 24; ?column?


122

(1 row)

seaboxsql=# SELECT timestamptz '2013-07-01 12:00:00' - timestamptz '2013-03-01 12:00:00'; ?column?


122 days (1 row)

seaboxsql=# SELECT age(timestamptz '2013-07-01 12:00:00', timestamptz '2013-03-01 12:00:00'); age


4 mons (1 row) ```

EXTRACT()/date_part()

语法
EXTRACT/date_part(field FROM source)
描述

extract/date_part函数从日期/时间值中抽取子域,例如年或者小时等。source 必须是一个类timestamptimeinterval的值表达式(类型为date的表达式将被造型为timestamp,并且因此也可以被同样使用)。field 是一个标识符或者字符串,它指定从源值中抽取的域。extract函数返回类型为double precision的值。 下列值是有效的域名字:

century

世纪

seaboxsql=# SELECT EXTRACT(CENTURY FROM TIMESTAMP '2000-12-16 12:21:13');
 date_part 
-----------
        20
(1 row)

seaboxsql=# SELECT EXTRACT(CENTURY FROM TIMESTAMP '2001-02-16 20:38:40');
 date_part 
-----------
        21
(1 row)

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

day

对于timestamp值,是(月份)里的日域(1-31);对于interval值,是日数

seaboxsql=# SELECT EXTRACT(DAY FROM TIMESTAMP '2001-02-16 20:38:40');
 date_part 
-----------
        16
(1 row)

seaboxsql=# SELECT EXTRACT(DAY FROM INTERVAL '40 days 1 minute');
 date_part 
-----------
        40
(1 row)
decade

年份域除以10

seaboxsql=# SELECT EXTRACT(DECADE FROM TIMESTAMP '2001-02-16 20:38:40');
 date_part 
-----------
       200
(1 row)
dow

一周中的日,从周日(0)到周六(6

seaboxsql=# SELECT EXTRACT(DOW FROM TIMESTAMP '2001-02-16 20:38:40');
 date_part 
-----------
         5
(1 row)

请注意,extract的一周中的日和to_char(..., 'D')函数不同。

doy

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

seaboxsql=# SELECT EXTRACT(DOY FROM TIMESTAMP '2001-02-16 20:38:40');
 date_part 
-----------
        47
(1 row)
epoch

对于timestamp with time zone值, 是自 1970-01-01 00:00:00 UTC 以来的秒数(结果可能是负数); 对于date andtimestamp值,是自本地时间 1970-01-01 00:00:00以来的描述;对于 interval值,它是时间间隔的总秒数。

seaboxsql=# SELECT EXTRACT(EPOCH FROM TIMESTAMP WITH TIME ZONE '2001-02-16 20:38:40.12-08');
  date_part   
--------------
 982384720.12
(1 row)

seaboxsql=# SELECT EXTRACT(EPOCH FROM INTERVAL '5 days 3 hours');
 date_part 
-----------
    442800
(1 row)

不能用to_timestamp把一个 epoch 值转换回成时间戳:

seaboxsql=# SELECT to_timestamp(982384720.12);
       to_timestamp        
---------------------------
 2001-02-17 12:38:40.12+08
(1 row)
hour

小时域(0 - 23)

seaboxsql=# SELECT EXTRACT(HOUR FROM TIMESTAMP '2001-02-16 20:38:40');
 date_part 
-----------
        20
(1 row)
isodow

一周中的日,从周一(1)到周日(7

seaboxsql=# SELECT EXTRACT(ISODOW FROM TIMESTAMP '2001-02-18 20:38:40');
 date_part 
-----------
         7
(1 row)

除了周日,这和dow相同。这符合ISO 8601 中一周中的日的编号。

isoyear

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

seaboxsql=# SELECT EXTRACT(ISOYEAR FROM DATE '2006-01-01');
 date_part 
-----------
      2005
(1 row)

seaboxsql=# SELECT EXTRACT(ISOYEAR FROM DATE '2006-01-02');
 date_part 
-----------
      2006
(1 row)

每一个ISO 8601周编号的年都开始于包含1月4日的那一周的周一,在早的1月或迟的12月中ISO年可能和格里高利年不同。更多信息见 week域。

这个域不能用于 PostgreSQL 8.3之前的版本。

microseconds

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

seaboxsql=# SELECT EXTRACT(MICROSECONDS FROM TIME '17:12:28.5');
 date_part 
-----------
  28500000
(1 row)
millennium

千年

seaboxsql=# SELECT EXTRACT(MILLENNIUM FROM TIMESTAMP '2001-02-16 20:38:40');
 date_part 
-----------
         3
(1 row)

19xx的年份在第二个千年里。第三个千年从 2001 年 1 月 1 日开始。

milliseconds

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

seaboxsql=# SELECT EXTRACT(MILLISECONDS FROM TIME '17:12:28.5');
 date_part 
-----------
     28500
(1 row)
minute

分钟域(0 - 59)

seaboxsql=# SELECT EXTRACT(MINUTE FROM TIMESTAMP '2001-02-16 20:38:40');
 date_part 
-----------
        38
(1 row)
month

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

seaboxsql=# SELECT EXTRACT(MONTH FROM TIMESTAMP '2001-02-16 20:38:40');
 date_part 
-----------
         2
(1 row)

seaboxsql=# SELECT EXTRACT(MONTH FROM INTERVAL '2 years 3 months');
 date_part 
-----------
         3
(1 row)

seaboxsql=# SELECT EXTRACT(MONTH FROM INTERVAL '2 years 13 months');
 date_part 
-----------
         1
(1 row)
quarter

该天所在的该年的季度(1 - 4)

seaboxsql=# SELECT EXTRACT(QUARTER FROM TIMESTAMP '2001-02-16 20:38:40');
 date_part 
-----------
         1
(1 row)
second

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

seaboxsql=# SELECT EXTRACT(SECOND FROM TIMESTAMP '2001-02-16 20:38:40');
 date_part 
-----------
        40
(1 row)

seaboxsql=# SELECT EXTRACT(SECOND FROM TIME '17:12:28.5');
 date_part 
-----------
      28.5
(1 row)
timezone
与 UTC 的时区偏移,以秒记。正数对应 UTC 东边的时区,负数对应 UTC西边的时区(从技术上来看,SeaboxSQL不使用UTC,因为其中不处理闰秒)。
timezone_hour
时区偏移的小时部分。
timezone_minute
时区偏移的分钟部分。
week

该天在所在的ISO 8601 周编号的年份里是第几周。根据定义, 一年的第一周包含该年的 1月 4 日并且 ISO周从星期一开始。换句话说,一年的第一个星期四在第一周。

在 ISO 周编号系统中,早的 1 月的日期可能位于前一年的第五十二或者第五十三周,而迟的 12 月的日期可能位于下一年的第一周。例如,2005-01-01位于 2004 年的第五十三周,并且2006-01-01位于 2005年的第五十二周,而2012-12-31位于 2013年的第一周。我们推荐把isoyear域和week一起使用来得到一致的结果。

seaboxsql=# SELECT EXTRACT(WEEK FROM TIMESTAMP '2001-02-16 20:38:40');
 date_part 
-----------
         7
(1 row)
year

年份域。要记住这里没有0 AD,所以从AD年里抽取BC年应该小心处理。

seaboxsql=# SELECT EXTRACT(YEAR FROM TIMESTAMP '2001-02-16 20:38:40');
 date_part 
-----------
      2001
(1 row)

注意

  • 当输入值为 ±Infinity时,extract对于单调增的域(epochjulianyearisoyeardecadecentury以及millennium)返回±Infinity。对于其他域返回 NULL。

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

date_trunc()

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

语法
date_trunc('field', source)
描述

source 是类型timestampinterval的值表达式(类型datetime的值都分别被自动转换成timestamp或者interval)。field 选择对输入值选用什么样的精度进行截断。返回的值是timestamp类型或者所有小于选定的精度的域都设置为零(或者一,对于日期和月份)的interval

field 的有效值是:

microseconds
milliseconds
second
minute
hour
day
week
month
quarter
year
decade
century
millennium
示例

``` sql seaboxsql=# SELECT date_trunc('hour', TIMESTAMP '2001-02-16 20:38:40'); date_trunc


2001-02-16 20:00:00 (1 row)

seaboxsql=# SELECT date_trunc('year', TIMESTAMP '2001-02-16 20:38:40'); date_trunc


2001-01-01 00:00:00 (1 row) ```

AT TIME ZONE

AT TIME ZONE把时间戳 without time zone 转换成时间戳 with time zone 或者反过来,并且把time 值转换成不同的时区。如下,AT TIME ZONE变体展示了它的变体。

timestamp without time zone
语法
timestamp without time zone AT TIME ZONE zone
返回类型
timestamp with time zone
描述
把给定的不带时区 的时间戳当作位于指定时区的时间对待
timestamp with time zone
语法
timestamp with time zone AT TIME ZONE zone
返回类型
timestamp without time zone
描述
把给定的带时区 的时间戳转换到新的时区,不带时区指定
time with time zone
语法
time with time zone AT TIME ZONE zone
返回类型
time with time zone
描述
把给定的带时区 的时间转换到新时区

在这些表达式里,我们需要的时区 zone 可以指定为文本串(例如,'America/Los_Angeles')或者一个间隔(例如,INTERVAL '-08:00')。

在文本情况下,可用的时区名字可以用时区中描述的任何方式指定。

示例

(假设本地时区是Asia/Shanghai

seaboxsql=# SELECT TIMESTAMP '2001-02-16 20:38:40' AT TIME ZONE 'America/Denver';
        timezone        
------------------------
 2001-02-17 11:38:40+00
(1 row)

seaboxsql=# SELECT TIMESTAMP WITH TIME ZONE '2001-02-16 20:38:40-05' AT TIME ZONE 'America/Denver';
      timezone       
---------------------
 2001-02-16 18:38:40
(1 row)

seaboxsql=# SELECT TIMESTAMP '2001-02-16 20:38:40-05' AT TIME ZONE 'Asia/Tokyo' AT TIME ZONE 'America/Chicago';
      timezone       
---------------------
 2001-02-16 05:38:40
(1 row)

第一个例子给缺少时区的值加上了时区,并且显示了使用当前TimeZone设置的值。第二个例子把带有时区值的时间戳移动到指定的时区,并且返回不带时区的值。这允许存储和显示不同于当前TimeZone设置的值。第三个例子把东京时间转换成芝加哥时间。把time值转换成其他时区会使用当前活跃的时区规则,因为没有提供日期。

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

当前日期/时间

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

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

CURRENT_TIMECURRENT_TIMESTAMP传递带有时区的值;LOCALTIMELOCALTIMESTAMP传递的值不带时区。

CURRENT_TIMECURRENT_TIMESTAMPLOCALTIMELOCALTIMESTAMP可以有选择地接受一个精度参数,该精度导致结果的秒域被园整为指定小数位。如果没有精度参数,结果将被给予所能得到的全部精度。

一些例子:

seaboxsql=# SELECT CURRENT_TIME;
    current_time    
--------------------
 03:06:52.430152+00
(1 row)

seaboxsql=# SELECT CURRENT_DATE;
 current_date 
--------------
 2022-02-28
(1 row)

seaboxsql=# SELECT CURRENT_TIMESTAMP;
       current_timestamp       
-------------------------------
 2022-02-28 03:06:52.431095+00
(1 row)

seaboxsql=# SELECT CURRENT_TIMESTAMP(2);
     current_timestamp     
---------------------------
 2022-02-28 03:06:52.43+00
(1 row)

seaboxsql=# SELECT LOCALTIMESTAMP;
       localtimestamp       
----------------------------
 2022-02-28 03:06:53.324666
(1 row)

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

SeaboxSQL同样也提供了返回当前语句开始时间的函数,它们会返回函数被调用时的真实当前时间。这些非 SQL 标准的函数列表如下:

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

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

所有日期/时间类型还接受特殊的文字值now,用于指定当前的日期和时间(重申,被解释为当前事务的开始时刻)。 因此,下面三个都返回相同的结果:

seaboxsql=# SELECT CURRENT_TIMESTAMP;
       current_timestamp       
-------------------------------
 2022-02-28 03:07:42.257556+00
(1 row)

seaboxsql=# SELECT now();
              now              
-------------------------------
 2022-02-28 03:07:42.258282+00
(1 row)

-- 对于和 DEFAULT 一起使用是不正确的
seaboxsql=# SELECT TIMESTAMP 'now';
         timestamp          
----------------------------
 2022-02-28 03:07:42.910342
(1 row)

注意

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

延时执行(pg_sleep()及其变体)

下面的这些函数可以用于让服务器进程延时执行:

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则可以用来休眠到一个指定的时刻唤醒。例如:

seaboxsql=# SELECT pg_sleep(1.5);
 pg_sleep 
----------
 
(1 row)

seaboxsql=# SELECT pg_sleep_for('5 minutes');
 pg_sleep_for 
--------------
 
(1 row)

seaboxsql=# SELECT pg_sleep_until('tomorrow 03:00');
 pg_sleep_until 
----------------
 
(1 row)

注意

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

警告

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

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