时间/日期函数和操作符
时间/日期函数和操作符¶
日期/时间函数展示了可用于处理日期/时间值的函数,其细节在随后的小节中描述。日期/时间操作符演示了基本算术操作符(+、*等)的行为。而与格式化相关的函数,可以参考数据类型格式化函数。你应该很熟悉日期/时间类型中的日期/时间数据类型的背景知识。
所有下文描述的接受time或timestamp输入的函数和操作符实际上都有两种变体: 一种接收time with time zone或timestamp 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(
fieldfrom[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(
yearint,monthint,dayint) - 返回类型
- date
- 描述
- 从年、月、日域创建日期
- 示例
- ``` sql
seaboxsql=# select make_date(2013, 7, 15);
make_date
2013/7/15 (1 row) ```
make_interval()¶
- 语法
- make_interval(
yearsint DEFAULT 0, int DEFAULT 0,weeksint DEFAULT 0,daysint DEFAULT 0,hoursint DEFAULT 0,minsint DEFAULT 0,secsdouble precision DEFAULT 0.0) - 返回类型
- interval
- 描述
- 从年、月、周、日、时、分、秒域创建 interval
- 示例
-
``` sql seaboxsql=# select make_interval(days => 10); make_interval
10 days(1 row) ```
make_time()¶
- 语法
- make_time(
hourint,minint,secdouble precision) - 返回类型
- time
- 描述
- 从时、分、秒域创建时间
- 示例
- ``` sql
seaboxsql=# select make_time(8, 15, 23.5);
make_time
08:15:23.5 (1 row) ```
make_timestamp()¶
- 语法
- make_timestamp(
yearsint,monthsint,daysint,hourint,minint,secdouble 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(
yearsint,monthsint,daysint,hourint,minint,secdouble precision, [timezonetext]) - 返回类型
- 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,除非start和end相等,这种情况下它表示单个时间实例。例如这表示两个只有一个共同端点的时间段不重叠。 - 示例
-
``` 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必须是一个类timestamp、time或interval的值表达式(类型为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 以来的秒数(结果可能是负数); 对于dateandtimestamp值,是自本地时间 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对于单调增的域(epoch、julian、year、isoyear、decade、century以及millennium)返回±Infinity。对于其他域返回 NULL。 -
extract函数主要的用途是做计算性处理。对于用于显示的日期/时间值格式化,参阅"数据类型格式化函数"。
date_trunc()¶
date_trunc函数在概念上和用于数字的trunc函数类似。
- 语法
date_trunc('field', source)- 描述
-
source是类型timestamp或interval的值表达式(类型date和time的值都分别被自动转换成timestamp或者interval)。field选择对输入值选用什么样的精度进行截断。返回的值是timestamp类型或者所有小于选定的精度的域都设置为零(或者一,对于日期和月份)的interval。field的有效值是:microsecondsmillisecondssecondminutehourdayweekmonthquarteryeardecadecenturymillennium - 示例
-
``` 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_TIME和CURRENT_TIMESTAMP传递带有时区的值;LOCALTIME和LOCALTIMESTAMP传递的值不带时区。
CURRENT_TIME、CURRENT_TIMESTAMP、LOCALTIME和LOCALTIMESTAMP可以有选择地接受一个精度参数,该精度导致结果的秒域被园整为指定小数位。如果没有精度参数,结果将被给予所能得到的全部精度。
一些例子:
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