# 9.9.日期/时间函数和运算符
表9.32显示了日期/时间值处理的可用功能,详细信息见以下小节。表9.31说明了基本算术运算符的行为(+
,*
等等)。有关格式化功能,请参阅第9.8节。您应该熟悉来自的日期/时间数据类型的背景信息第8.5节.
此外,中显示的常用比较运算符表9.1可用于日期/时间类型。日期和时间戳(带或不带时区)都是可比较的,而时间(带或不带时区)和间隔只能与相同数据类型的其他值进行比较。当比较不带时区的时间戳和带时区的时间戳时,假设前一个值在时区配置参数,并旋转到UTC,以便与后一个值(内部已在UTC中)进行比较。类似地,假定日期值表示时区
将其与时间戳进行比较时的区域。
下面描述的所有函数和运算符时间
或时间戳
输入实际上有两种变体:一种是带时区的时间
或带时区的时间戳
,还有一个没有时区的时间
或不带时区的时间戳
.为简洁起见,这些变体未单独显示。还有+
和*
运算符以交换对的形式出现(例如,两者都有)日期
+
整数
和整数
+
日期
); 我们只展示了每一对中的一个。
表9.31.日期/时间运算符
操作人员 描述 例子 |
---|
日期 + 整数 → 日期 给日期加上天数 日期'2001-09-28'+7 → 2001-10-05 |
日期 + 间隔 → 时间戳 为日期添加间隔 日期'2001-09-28'+间隔'1小时' → 2001-09-28 01:00:00 |
日期 + 时间 → 时间戳 在日期中添加一天中的某个时间 日期'2001-09-28'+时间'03:00' → 2001-09-28 03:00:00 |
间隔 + 间隔 → 间隔 添加间隔 间隔“1天”+间隔“1小时” → 1天01:00:00 |
时间戳 + 间隔 → 时间戳 向时间戳添加间隔 时间戳'2001-09-28 01:00'+间隔'23小时' → 2001-09-29 00:00:00 |
时间 + 间隔 → 时间 给时间加一个间隔 时间'01:00'+间隔'3小时' → 04:00:00 |
- 间隔 → 间隔 否定间隔 -间隔23小时 → -23:00:00 |
日期 - 日期 → 整数 减去日期,生成经过的天数 日期'2001-10-01'-日期'2001-09-28' → 3. |
日期 - 整数 → 日期 从日期中减去天数 日期'2001-10-01'-7 → 2001-09-24 |
日期 - 间隔 → 时间戳 从日期中减去间隔 日期'2001-09-28'-间隔'1小时' → 2001-09-27 23:00:00 |
时间 - 时间 → 间隔 减去次数 时间'05:00'-时间'03:00' → 02:00:00 |
时间 - 间隔 → 时间 从时间中减去间隔 时间'05:00'-间隔'2小时' → 03:00:00 |
时间戳 - 间隔 → 时间戳 从时间戳中减去间隔 时间戳'2001-09-28 23:00'-间隔'23小时' → 2001-09-28 00:00:00 |
间隔 - 间隔 → 间隔 减去间隔 间隔 '1 天' - 间隔 '1 小时' → 1天-01:00:00 |
时间戳 - 时间戳 → 间隔 减去时间戳(将 24 小时间隔转换为天,类似于 justify_hours() )时间戳'2001-09-29 03:00' - 时间戳'2001-07-27 12:00' → 63 天 15:00:00 |
间隔 * 双精度 → 间隔 将一个区间乘以一个标量 间隔“1秒”* 900 → 00:15:00 间隔 '1 天' * 21 → 21 天 间隔 '1 小时' * 3.5 →03:30:00 |
间隔 / 双精度 →间隔 用标量除区间 间隔1小时/1.5 →00:40:00 |
表9.32.日期/时间函数
作用 描述 例子 |
---|
年龄 (时间戳 ,时间戳 ) →间隔 减去参数,产生一个“象征性”的结果,使用年和月,而不仅仅是天 年龄(时间戳'2001-04-10',时间戳'1957-06-13') →43年9月27日 |
年龄 (时间戳 ) →间隔 从中减去参数 当前日期 (午夜时分)年龄(时间戳“1957-06-13”) → 62年6月10日 |
时钟时间戳 ( ) → 带时区的时间戳 当前日期和时间(报表执行期间的更改);看见第9.9.5节 时钟时间戳() → 2019-12-23 14:39:53.662522-05 |
当前日期 → 日期 当前日期;看见第9.9.5节 当前日期 → 2019-12-23 |
当前时间 → 带时区的时间 一天中的当前时间;看见第9.9.5节 当前时间 → 14:39:53.662522-05 |
当前时间 ( 整数 ) → 带时区的时间 当前时间,精度有限;看见第9.9.5节 当前_时间(2) → 14:39:53.66-05 |
当前时间戳 → 带时区的时间戳 当前日期和时间(当前交易的开始);看见第9.9.5节 当前时间戳 → 2019-12-23 14:39:53.662522-05 |
当前时间戳 ( 整数 ) → 带时区的时间戳 当前日期和时间(当前交易的开始),精度有限;看见第9.9.5节 当前时间戳(0) → 2019-12-23 14:39:53-05 |
date_bin ( 间隔 , 时间戳 , 时间戳 ) → 时间戳 Bin输入到与指定原点对齐的指定间隔;看见第9.9.3节 日期(“15分钟”,时间戳“2001-02-16 20:38:40”,时间戳“2001-02-16 20:05:00”) → 2001-02-16 20:35:00 |
日期部分 ( 文本 , 时间戳 ) → 双精度 获取时间戳子字段(相当于 摘录 ); 看见第9.9.1节日期部分(“小时”,时间戳“2001-02-16 20:38:40”) → 20 |
日期部分 ( 文本 , 间隔 ) → 双精度 获取间隔子字段(相当于 摘录 ); 看见第9.9.1节日期部分(“月”,间隔“2年3个月”) → 3. |
日期 ( 文本 , 时间戳 ) → 时间戳 截断到规定的精度;看见第9.9.2节 日期(“小时”,时间戳“2001-02-16 20:38:40”) → 2001-02-16 20:00:00 |
日期 ( 文本 , 带时区的时间戳 , 文本 ) → 带时区的时间戳 在指定的时区内截断到指定的精度;看见第9.9.2节 日期:澳大利亚/悉尼2001-02-16 20:38:40+00 → 2001-02-16 13:00:00+00 |
日期 ( 文本 , 间隔 ) → 间隔 截断到规定的精度;看见第9.9.2节 日期(“小时”,间隔“2天3小时40分钟”) → 2天03:00:00 |
摘录 ( 领域 从…起 时间戳 ) → 数字的 获取时间戳子字段;看见第9.9.1节 摘录(时间戳'2001-02-16 20:38:40'后的小时) → 20 |
摘录 ( 领域 从…起 间隔 ) → 数字的 得到区间子域;看见第9.9.1节 摘录(间隔“2年3个月”后的一个月) → 3. |
是有限的 ( 日期 ) → 布尔值 有限日期测试(非+/-无限) isfinite(日期'2001-02-16') → 符合事实的 |
是有限的 ( 时间戳 ) → 布尔值 有限时间戳测试(非+/-无限) isfinite(时间戳“无穷大”) → 错误的 |
是有限的 ( 间隔 ) → 布尔值 有限间隔测试(当前始终为真) IsLimited(间隔“4小时”) → 符合事实的 |
证明…天 ( 间隔 ) → 间隔 调整时间间隔,使30天的时间段表示为月 调整天数(间隔“35天”) → 1个周一5天 |
合理的工作时间 ( 间隔 ) → 间隔 调整时间间隔,使24小时时间段表示为天 调整小时数(间隔“27小时”) → 1天03:00:00 |
调整间隔 ( 间隔 ) → 间隔 使用 证明…天 和合理的工作时间 ,并进行额外的标志调整调整间隔(间隔“1个月-1个小时”) → 29天23:00:00 |
本地时间 → 时间 一天中的当前时间;看见第9.9.5节 本地时间 → 14:39:53.662522 |
本地时间 ( 整数 ) → 时间 当前时间,精度有限;看见第9.9.5节 本地时间(0) → 14:39:53 |
本地时间戳 → 时间戳 当前日期和时间(当前交易的开始);看见第9.9.5节 本地时间戳 → 2019-12-23 14:39:53.662522 |
本地时间戳 ( 整数 ) → 时间戳 当前日期和时间(当前交易的开始),精度有限;看见第9.9.5节 本地时间戳(2) → 2019-12-23 14:39:53.66 |
约会 ( 年 智力 , 月 智力 , 白天 智力 ) → 日期 从年、月和日字段创建日期(负年份表示BC) 制作日期(2013年7月15日) → 2013-07-15 |
作间歇 ( [ 年 智力 [, 月 智力 [, 周 智力 [, 天 智力 [, 小时 智力 [, 分钟 智力 [, 秒 双精度 ]]]]]]] ) → 间隔 从年、月、周、天、小时、分钟和秒字段创建间隔,每个字段都可以默认为零 制造间隔(天数=>10天) → 10天 |
争取时间 ( 小时 智力 , 闵 智力 , 秒 双精度 ) → 时间 从小时、分钟和秒字段创建时间 制造时间(8,15,23.5) → 08:15:23.5 |
制作时间戳 ( 年 智力 , 月 智力 , 白天 智力 , 小时 智力 , 闵 智力 , 秒 双精度 ) → 时间戳 从年、月、日、时、分和秒字段创建时间戳(负年份表示BC) 制作时间戳(2013,7,15,8,15,23.5) → 2013-07-15 08:15:23.5 |
使…变得更好 ( 年 智力 , 月 智力 , 白天 智力 , 小时 智力 , 闵 智力 , 秒 双精度 [, 时区 文本 ] ) → 带时区的时间戳 从年、月、日、时、分和秒字段创建带有时区的时间戳(负年份表示BC)。如果* 时区 *如果未指定,则使用当前时区;示例假定会话时区为欧洲/伦敦 make_Timestamtz(2013,7,15,8,15,23.5) → 2013-07-15 08:15:23.5+01 make_Timestamtz(2013年7月15日8月15日23.5日《美国/纽约》) → 2013-07-15 13:15:23.5+01 |
现在 ( ) → 带时区的时间戳 当前日期和时间(当前交易的开始);看见第9.9.5节 现在() → 2019-12-23 14:39:53.662522-05 |
语句时间戳 ( ) → 带时区的时间戳 当前日期和时间(当前报表的开始);看见第9.9.5节 语句_timestamp() → 2019-12-23 14:39:53.662522-05 |
时间 ( ) → 文本 当前日期和时间(如 时钟时间戳 ,但作为一个文本 字符串);看见第9.9.5节每日时间 → 周一12月23日14:39:53.662522 2019美国东部时间 |
事务时间戳 ( ) → 带时区的时间戳 当前日期和时间(当前交易的开始);看见第9.9.5节 事务_时间戳() → 2019-12-23 14:39:53.662522-05 |
到时间戳 ( 双精度 ) → 带时区的时间戳 将Unix历元(自1970-01-01 00:00:00+00起的秒数)转换为带时区的时间戳 to_时间戳(1284352323) → 2010-09-13 04:32:03+00 |
(start1, end1) OVERLAPS (start2, end2)
(start1, length1) OVERLAPS (start2, length2)
当两个时间段(由它们的端点定义)重叠时,此表达式产生true,当它们不重叠时产生false。端点可以指定为日期、时间或时间戳对;或者作为日期、时间或时间戳,后跟间隔。当提供一对值时,可以先写入开始或结束;重叠
自动将该对的较早值作为起始值。每个时间段被视为代表半开放时间间隔*开始
* <=
时间
<
*终止
除非开始
和终止
*都是相等的,在这种情况下,它代表单一的时间瞬间。例如,这意味着只有一个共同端点的两个时间段不会重叠。
SELECT (DATE '2001-02-16', DATE '2001-12-21') OVERLAPS
(DATE '2001-10-30', DATE '2002-10-30');
Result: true
SELECT (DATE '2001-02-16', INTERVAL '100 days') OVERLAPS
(DATE '2001-10-30', DATE '2002-10-30');
Result: false
SELECT (DATE '2001-10-29', DATE '2001-10-30') OVERLAPS
(DATE '2001-10-30', DATE '2001-10-31');
Result: false
SELECT (DATE '2001-10-30', DATE '2001-10-30') OVERLAPS
(DATE '2001-10-30', DATE '2001-10-31');
Result: true
当添加间隔
值(或减去间隔
(a)价值带时区的时间戳
值,则天数组件提前或减少日期带时区的时间戳
按照指定的天数,保持一天的时间不变。在夏令时变化期间(当会话时区设置为可识别DST的时区时),这意味着间隔“1天”
不一定等于“24小时”间隔
。例如,会话时区设置为美国/丹佛
:
SELECT timestamp with time zone '2005-04-02 12:00:00-07' + interval '1 day';
Result: 2005-04-03 12:00:00-06
SELECT timestamp with time zone '2005-04-02 12:00:00-07' + interval '24 hours';
Result: 2005-04-03 13:00:00-06
发生这种情况的原因是,由于夏令时的变化,一个小时被跳过2005-04-03 02:00:00
时区美国/丹佛
.
请注意,可能存在歧义月
返回的字段年龄
因为不同的月份有不同的天数。PostgreSQL的方法在计算部分月份时使用两个日期中较早日期的月份。例如年龄('2004-06-01'、'2004-04-30')
利用四月收获1个周一1天
,而使用May会产生1个周一2天
因为五月有31天,而四月只有30天。
日期和时间戳的减法也可能很复杂。从概念上讲,执行减法的一种简单方法是使用摘自
,然后减去结果;这就产生了秒在这两个值之间。这将根据每个月的天数、时区变化和夏令时调整进行调整。将日期或时间戳值减去“-
“操作员返回两个值之间的天数(24小时)和小时/分/秒,并进行相同的调整。这个年龄
函数返回年、月、日和时/分/秒,逐字段执行减法,然后调整字段负值。以下查询说明了这些方法的差异。样本结果是用时区='美国/东部'
; 使用的两个日期之间存在夏令时变化:
SELECT EXTRACT(EPOCH FROM timestamptz '2013-07-01 12:00:00') -
EXTRACT(EPOCH FROM timestamptz '2013-03-01 12:00:00');
Result: 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;
Result: 121.958333333333
SELECT timestamptz '2013-07-01 12:00:00' - timestamptz '2013-03-01 12:00:00';
Result: 121 days 23:00:00
SELECT age(timestamptz '2013-07-01 12:00:00', timestamptz '2013-03-01 12:00:00');
Result: 4 mons
# 9.9.1. 摘录
, 日期部分
EXTRACT(field FROM source)
这个摘录
函数从日期/时间值中检索子字段,如年或小时。*来源
必须是类型为的值表达式时间戳
, 时间
或间隔
类型表达式日期
投靠时间戳
因此也可以使用。)领域
*是一个标识符或字符串,用于选择要从源值中提取的字段。这个摘录
函数返回类型为的值数字的
。以下是有效的字段名:
100年
世纪
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,尽管当时他们并不知道。该定义适用于所有公历国家。没有世纪数字0,从-1世纪到1世纪。如果您不同意这一点,请将您的投诉写信给:罗马教皇,梵蒂冈圣彼得大教堂。
白天
对于时间戳
值,日期字段(1-31);对于间隔
值,天数
SELECT EXTRACT(DAY FROM TIMESTAMP '2001-02-16 20:38:40');
Result: 16
SELECT EXTRACT(DAY FROM INTERVAL '40 days 1 minute');
Result: 40
十年
年份字段除以10
SELECT EXTRACT(DECADE FROM TIMESTAMP '2001-02-16 20:38:40');
Result: 200
陶氏
星期天一周中的一天(0
)到周六(6.
)
SELECT EXTRACT(DOW FROM TIMESTAMP '2001-02-16 20:38:40');
Result: 5
注意摘录
的星期日编号不同于to_char(…,'D')
作用
多伊
一年中的某一天(1-365/366)
SELECT EXTRACT(DOY FROM TIMESTAMP '2001-02-16 20:38:40');
Result: 47
纪元
对于带时区的时间戳
值,自1970-01-01 00:00:00 UTC以来的秒数(之前的时间戳为负数);对于日期
和时间戳
值,自1970-01-01 00:00:00以来的标称秒数,不考虑时区或夏令时规则;对于间隔
值,间隔中的总秒数
SELECT EXTRACT(EPOCH FROM TIMESTAMP WITH TIME ZONE '2001-02-16 20:38:40.12-08');
Result: 982384720.12
SELECT EXTRACT(EPOCH FROM TIMESTAMP '2001-02-16 20:38:40.12');
Result: 982355920.12
SELECT EXTRACT(EPOCH FROM INTERVAL '5 days 3 hours');
Result: 442800
可以将历元值转换回带时区的时间戳
具有到时间戳
:
SELECT to_timestamp(982384720.12);
Result: 2001-02-17 04:38:40.12+00
当心这件事到时间戳
从一个时代中提取日期
或时间戳
值可能会产生误导性的结果:结果将有效地假定原始值是以UTC给出的,但情况可能并非如此。
小时
小时字段(0-23)
SELECT EXTRACT(HOUR FROM TIMESTAMP '2001-02-16 20:38:40');
Result: 20
伊索多
一周中的一天,如星期一(1.
)到星期天(7.
)
SELECT EXTRACT(ISODOW FROM TIMESTAMP '2001-02-18 20:38:40');
Result: 7
这和陶氏
除了星期天。这与ISO 8601的一周工作日编号相匹配。
等年
日期所在的ISO 8601周编号年份(不适用于间隔)
SELECT EXTRACT(ISOYEAR FROM DATE '2006-01-01');
Result: 2005
SELECT EXTRACT(ISOYEAR FROM DATE '2006-01-02');
Result: 2006
每个ISO 8601周编号年从包含1月4日的星期一开始,因此在1月初或12月底,ISO年可能不同于公历年。看到了吗周
字段以获取更多信息。
此字段在8.3之前的PostgreSQL版本中不可用。
朱利安
这个朱利安日期对应于日期或时间戳(不适用于间隔)。非本地午夜的时间戳会产生一个分数值。看见B.7节了解更多信息。
SELECT EXTRACT(JULIAN FROM DATE '2006-01-01');
Result: 2453737
SELECT EXTRACT(JULIAN FROM TIMESTAMP '2006-01-01 12:00');
Result: 2453737.50000000000000000000
微秒
秒字段(包括小数部分)乘以1 000 000;请注意,这包括完整的秒数
SELECT EXTRACT(MICROSECONDS FROM TIME '17:12:28.5');
Result: 28500000
一千年
千禧年
SELECT EXTRACT(MILLENNIUM FROM TIMESTAMP '2001-02-16 20:38:40');
Result: 3
20世纪是第二个千年。第三个千年始于2001年1月1日。
毫秒
秒字段(包括小数部分)乘以1000.请注意,这包括完整的秒数。
SELECT EXTRACT(MILLISECONDS FROM TIME '17:12:28.5');
Result: 28500
分钟
分钟字段(0-59)
SELECT EXTRACT(MINUTE FROM TIMESTAMP '2001-02-16 20:38:40');
Result: 38
月
对于时间戳
值,一年中的月份数(1-12);对于间隔
值,月数,模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
一刻钟
日期所在的季度(1-4)
SELECT EXTRACT(QUARTER FROM TIMESTAMP '2001-02-16 20:38:40');
Result: 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
时区
与UTC的时区偏移量,以秒为单位。正值对应UTC以东的时区,负值对应UTC以西的时区。(从技术上讲,PostgreSQL不使用UTC,因为不处理闰秒。)
时区每小时
时区偏移的小时分量
时区每分钟
时区偏移的分钟分量
周
ISO 8601周的编号为一年中的第几周。根据定义,ISO周从周一开始,一年中的第一周包括该年的1月4日。换句话说,一年中的第一个星期四是在那一年的第一周。
在ISO周编号系统中,1月初日期可能是前一年第52或53周的一部分,12月底日期可能是下一年第一周的一部分。例如2005-01-01
是2004年第53周的一部分2006-01-01
是2005年第52周的一部分2012-12-31
是2013年第一周的一部分。建议使用等年
和周
以获得一致的结果。
SELECT EXTRACT(WEEK FROM TIMESTAMP '2001-02-16 20:38:40');
Result: 7
年
年场。请记住,没有公元0年
所以减去公元前
多年以后公元
年复一年都要小心。
SELECT EXTRACT(YEAR FROM TIMESTAMP '2001-02-16 20:38:40');
Result: 2001
# 笔记
当输入值为+/-无穷大时,摘录
对于单调递增的字段,返回+/-无穷大(纪元
, 朱利安
, 年
, 等年
, 十年
, 100年
和一千年
)。对于其他字段,返回NULL。9.6之前的PostgreSQL版本在所有无限输入情况下都返回零。
这个摘录
函数主要用于计算处理。有关设置显示日期/时间值的格式,请参见第9.8节.
这个日期部分
函数是在与SQL标准函数等效的传统Ingres上建模的摘录
:
date_part('field', source)
注意这里*领域
*参数必须是字符串值,而不是名称。的有效字段名日期部分
都是一样的摘录
.由于历史原因日期部分
函数返回类型为的值双精度
。在某些用途中,这可能会导致精度下降。使用摘录
建议改为。
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(field, source [, time_zone ])
*来源
是类型的值表达式时间戳
, 带时区的时间戳
或间隔
类型值日期
和时间
自动转换为时间戳
或间隔
(分别为)领域
*选择截断输入值的精度。返回值的类型类似时间戳
, 带时区的时间戳
或间隔
,并且它的所有字段的重要性都低于所选字段,并将其设置为零(或一个字段,表示日期和月份)。
的有效值*领域
*是:
微秒 |
---|
毫秒 |
第二 |
分钟 |
小时 |
白天 |
周 |
月 |
一刻钟 |
年 |
十年 |
100年 |
一千年 |
当输入值为带时区的时间戳
,就特定时区执行截断;例如,截断到白天
生成该区域中午夜的值。默认情况下,截断是针对当前时区设置,但选项是可选的*时区
*参数可以指定不同的时区。时区名称可以使用中描述的任何方式指定第8.5.3节.
处理时无法指定时区不带时区的时间戳
或间隔
输入。这些都是从表面上看的。
示例(假设本地时区为美国/纽约
):
SELECT date_trunc('hour', TIMESTAMP '2001-02-16 20:38:40');
Result: 2001-02-16 20:00:00
SELECT date_trunc('year', TIMESTAMP '2001-02-16 20:38:40');
Result: 2001-01-01 00:00:00
SELECT date_trunc('day', TIMESTAMP WITH TIME ZONE '2001-02-16 20:38:40+00');
Result: 2001-02-16 00:00:00-05
SELECT date_trunc('day', TIMESTAMP WITH TIME ZONE '2001-02-16 20:38:40+00', 'Australia/Sydney');
Result: 2001-02-16 08:00:00-05
SELECT date_trunc('hour', INTERVAL '3 days 02:47:33');
Result: 3 days 02:00:00
# 9.9.3. date_bin
功能date_bin
“bins”将输入时间戳设置为指定的时间间隔(大步走)与指定的原点对齐。
date_bin(stride, source, origin)
*来源
*是类型的值表达式时间戳
或带时区的时间戳
类型值日期
自动转换为时间戳
.) *大步走
是类型的值表达式间隔
.返回值的类型与此类似时间戳
或带时区的时间戳
,它标志着垃圾箱的开始来源
*被放置。
例如:
SELECT date_bin('15 minutes', TIMESTAMP '2020-02-11 15:44:17', TIMESTAMP '2001-01-01');
Result: 2020-02-11 15:30:00
SELECT date_bin('15 minutes', TIMESTAMP '2020-02-11 15:44:17', TIMESTAMP '2001-01-01 00:02:30');
Result: 2020-02-11 15:32:30
在满单位(1分钟、1小时等)的情况下,它给出的结果与类似的结果相同日期
打电话,但区别在于date_bin
可以截断为任意间隔。
这个*大步走
*间隔必须大于零,并且不能包含月或更大的单位。
# 9.9.4. 在时区
这个在时区
运算符转换时间戳没有时区到/从时间戳具有时区,以及带时区的时间
不同时区的值。表9.33显示其变体。
表9.33. 在时区
变体
操作人员 描述 例子 |
---|
不带时区的时间戳 在时区 区 → 带时区的时间戳 转换给定的时间戳没有时区到时间戳具有时区,假设给定值位于指定的时区中。 时区“美国/丹佛”的时间戳“2001-02-16 20:38:40” → 2001-02-17 03:38:40+00 |
带时区的时间戳 在时区 区 → 不带时区的时间戳 转换给定的时间戳具有时区到时间戳没有时区,因为时间会出现在该时区中。 时区“美国/丹佛”上带有时区“2001-02-16 20:38:40-05”的时间戳 → 2001-02-16 18:38:40 |
带时区的时间 在时区 区 → 带时区的时间 在给定的时间内具有时区到新时区。由于未提供日期,因此将使用指定目的地区域的当前活动UTC偏移量。 时区为“UTC”的时区为“05:34:17-05” → 10:34:17+00 |
在这些表达式中,所需的时区*区
*可以指定为文本值(例如。,“美国/洛杉矶”
)或作为间隔(例如。,间隔时间“-08:00”
)。在文本情况下,时区名称可以使用中描述的任何方式指定第8.5.3节.间隔情况仅适用于与UTC有固定偏移的区域,因此在实践中并不常见。
示例(假设当前时区背景是美国/洛杉矶
):
SELECT TIMESTAMP '2001-02-16 20:38:40' AT TIME ZONE 'America/Denver';
Result: 2001-02-16 19:38:40-08
SELECT TIMESTAMP WITH TIME ZONE '2001-02-16 20:38:40-05' AT TIME ZONE 'America/Denver';
Result: 2001-02-16 18:38:40
SELECT TIMESTAMP '2001-02-16 20:38:40' AT TIME ZONE 'Asia/Tokyo' AT TIME ZONE 'America/Chicago';
Result: 2001-02-16 05:38:40
第一个示例向缺少时区的值添加时区,并使用当前时区显示该值时区
背景第二个示例将带有时区值的时间戳移到指定的时区,并返回不带时区的值。这允许存储和显示与当前值不同的值时区
背景第三个例子将东京时间转换为芝加哥时间。
功能``时区(*
区*, *
时间戳*)
相当于符合SQL的构造*
时间戳*在时区*
区*
.
# 9.9.5.当前日期/时间
PostgreSQL提供了许多函数,可以返回与当前日期和时间相关的值。这些SQL标准函数都基于当前事务的开始时间返回值:
CURRENT_DATE
CURRENT_TIME
CURRENT_TIMESTAMP
CURRENT_TIME(precision)
CURRENT_TIMESTAMP(precision)
LOCALTIME
LOCALTIMESTAMP
LOCALTIME(precision)
LOCALTIMESTAMP(precision)
当前时间
和当前时间戳
用时区传递价值观;本地时间
和本地时间戳
提供没有时区的价值观。
当前时间
, 当前时间戳
, 本地时间
和本地时间戳
可以选择使用精度参数,这会导致结果在秒字段中四舍五入到小数位数。如果没有精度参数,结果将以完全可用的精度给出。
例如:
SELECT CURRENT_TIME;
Result: 14:39:53.662522-05
SELECT CURRENT_DATE;
Result: 2019-12-23
SELECT CURRENT_TIMESTAMP;
Result: 2019-12-23 14:39:53.662522-05
SELECT CURRENT_TIMESTAMP(2);
Result: 2019-12-23 14:39:53.66-05
SELECT LOCALTIMESTAMP;
Result: 2019-12-23 14:39:53.662522
由于这些函数返回当前事务的开始时间,因此它们的值在事务期间不会更改。这被认为是一个特性:其目的是允许单个事务具有“当前”时间的一致概念,以便同一事务中的多个修改具有相同的时间戳。
# 笔记
其他数据库系统可能会更频繁地提升这些值。
PostgreSQL还提供返回当前语句的开始时间以及调用该函数时的实际当前时间的函数。非SQL标准时间函数的完整列表如下:
transaction_timestamp()
statement_timestamp()
clock_timestamp()
timeofday()
now()
事务_时间戳()
相当于当前时间戳
,但命名的目的是清楚地反映它的回报。语句_timestamp()
返回当前语句的开始时间(更具体地说,是从客户端接收最新命令消息的时间)。语句_timestamp()
和事务_时间戳()
在事务的第一个命令中返回相同的值,但在后续命令中可能会有所不同。时钟时间戳()
返回实际的当前时间,因此即使在单个SQL命令中,其值也会更改。每日时间
是一个历史悠久的PostgreSQL函数。喜欢时钟时间戳()
,它返回实际的当前时间,但格式为文本
而不是一根绳子带时区的时间戳
价值现在()
传统的PostgreSQL等同于事务_时间戳()
.
所有日期/时间数据类型也接受特殊的文本值现在
指定当前日期和时间(再次解释为事务开始时间)。因此,以下三个都返回相同的结果:
SELECT CURRENT_TIMESTAMP;
SELECT now();
SELECT TIMESTAMP 'now'; -- but see tip below
# 提示
在指定以后要计算的值时,不要使用第三种形式,例如在违约
表列的子句。系统将进行转换现在
到时间戳
一旦常量被解析,当需要默认值时,就会使用创建表的时间!前两个表单在使用默认值之前不会被计算,因为它们是函数调用。因此,它们将提供所需的行为,默认为行插入时间。(另见第8.5.1.4节.)
# 9.9.6.推迟执行
以下功能可用于延迟服务器进程的执行:
pg_sleep ( double precision )
pg_sleep_for ( interval )
pg_sleep_until ( timestamp with time zone )
pg_睡眠
使当前会话的进程处于休眠状态,直到给定的秒数结束。可以指定分数秒延迟。pg_睡眠_
是一个方便的函数,允许将睡眠时间指定为间隔
. 睡到
是一种方便的功能,用于在需要特定唤醒时间时使用。例如:
SELECT pg_sleep(1.5);
SELECT pg_sleep_for('5 minutes');
SELECT pg_sleep_until('tomorrow 03:00');
# 笔记
睡眠时间间隔的有效分辨率取决于平台;0.01秒是一个常见值。睡眠延迟将至少与指定的时间一样长。它可能会更长,这取决于服务器负载等因素。特别地,睡到
不能保证在指定的时间完全醒来,但不会更早醒来。
# 警告
确保您的会话在调用时所持有的锁不会超过需要的数量pg_睡眠
或者它的变种。否则,其他会话可能需要等待您的睡眠过程,从而降低整个系统的速度。