带时区的时间戳函数
本节介绍用于检查和操作 TIMESTAMP WITH TIME ZONE
(或 TIMESTAMPTZ)值的函数和运算符。另请参阅相关的 TIMESTAMP 函数。
时区支持由内置的 ICU 扩展提供。
在以下示例中,当前时区假定为 America/Los_Angeles,
并使用公历。
内置带时区时间戳函数
下表展示了 TIMESTAMPTZ 值可用的标量函数。
由于这些函数不涉及分箱或显示,
因此它们始终可用。
| 名称 | 说明 |
|---|---|
current_timestamp | 当前日期和时间(当前事务开始时)。 |
get_current_timestamp() | 当前日期和时间(当前事务开始时)。 |
greatest(timestamptz, timestamptz) | 两个时间戳中较晚的一个。 |
isfinite(timestamptz) | 若带时区时间戳是有限值则返回 true,否则返回 false。 |
isinf(timestamptz) | 若带时区时间戳是无穷值则返回 true,否则返回 false。 |
least(timestamptz, timestamptz) | 两个时间戳中较早的一个。 |
now() | 当前日期和时间(当前事务开始时)。 |
timetz_byte_comparable(timetz) | 将 TIME WITH TIME ZONE 转换为 UBIGINT 排序键。 |
to_timestamp(double) | 将自 epoch 以来的秒数转换为带时区时间戳。 |
transaction_timestamp() | 当前日期和时间(当前事务开始时)。 |
current_timestamp
| 说明 | 当前日期和时间(当前事务开始时)。 |
| 示例 | current_timestamp |
| 结果 | 2022-10-08 12:44:46.122-07 |
get_current_timestamp()
| 说明 | 当前日期和时间(当前事务开始时)。 |
| 示例 | get_current_timestamp() |
| 结果 | 2022-10-08 12:44:46.122-07 |
greatest(timestamptz, timestamptz)
| 说明 | 两个时间戳中较晚的一个。 |
| 示例 | greatest(TIMESTAMPTZ '1992-09-20 20:38:48', TIMESTAMPTZ '1992-03-22 01:02:03.1234') |
| 结果 | 1992-09-20 20:38:48-07 |
isfinite(timestamptz)
| 说明 | 若带时区时间戳是有限值则返回 true,否则返回 false。 |
| 示例 | isfinite(TIMESTAMPTZ '1992-03-07') |
| 结果 | true |
isinf(timestamptz)
| 说明 | 若带时区时间戳是无穷值则返回 true,否则返回 false。 |
| 示例 | isinf(TIMESTAMPTZ '-infinity') |
| 结果 | true |
least(timestamptz, timestamptz)
| 说明 | 两个时间戳中较早的一个。 |
| 示例 | least(TIMESTAMPTZ '1992-09-20 20:38:48', TIMESTAMPTZ '1992-03-22 01:02:03.1234') |
| 结果 | 1992-03-22 01:02:03.1234-08 |
now()
| 说明 | 当前日期和时间(当前事务开始时)。 |
| 示例 | now() |
| 结果 | 2022-10-08 12:44:46.122-07 |
timetz_byte_comparable(timetz)
| 说明 | 将 TIME WITH TIME ZONE 转换为 UBIGINT 排序键。 |
| 示例 | timetz_byte_comparable('18:18:16.21-07:00'::TIMETZ) |
| 结果 | 2494691656335442799 |
to_timestamp(double)
| 说明 | 将自 epoch 以来的秒数转换为带时区时间戳。 |
| 示例 | to_timestamp(1284352323.5) |
| 结果 | 2010-09-13 04:32:03.5+00 |
transaction_timestamp()
| 说明 | 当前日期和时间(当前事务开始时)。 |
| 示例 | transaction_timestamp() |
| 结果 | 2022-10-08 12:44:46.122-07 |
带时区时间戳字符串
在未加载时区扩展时,TIMESTAMPTZ 值与字符串之间的转换
将使用偏移量表示法。
这使你在没有时区信息的情况下也能正确指定一个时刻。
为了可移植性,TIMESTAMPTZ 值始终使用 GMT 偏移显示:
SELECT '2022-10-08 13:13:34-07'::TIMESTAMPTZ;
2022-10-08 20:13:34+00
如果加载了 ICU 等时区扩展,则可从字符串解析时区 并转换为本地时区表示:
SELECT '2022-10-08 13:13:34 Europe/Amsterdam'::TIMESTAMPTZ::VARCHAR;
2022-10-08 04:13:34-07 -- the offset will differ based on your local time zone
ICU 带时区时间戳运算符
下表展示了 TIMESTAMP WITH TIME ZONE 值可用的数学运算符,
这些运算符由 ICU 扩展提供。
| 运算符 | 说明 | 示例 | 结果 |
|---|---|---|---|
+ | 与 INTERVAL 相加 | TIMESTAMPTZ '1992-03-22 01:02:03' + INTERVAL 5 DAY | 1992-03-27 01:02:03 |
- | TIMESTAMPTZ 相减 | TIMESTAMPTZ '1992-03-27' - TIMESTAMPTZ '1992-03-22' | 5 days |
- | 减去 INTERVAL | TIMESTAMPTZ '1992-03-27 01:02:03' - INTERVAL 5 DAY | 1992-03-22 01:02:03 |
对无穷值进行加减运算会得到相同的无穷值。
ICU 带时区时间戳函数
下表展示了 ICU 为 TIMESTAMP WITH TIME ZONE 值提供的标量函数。
| 名称 | 说明 |
|---|---|
age(timestamptz, timestamptz) | 参数相减,得到两个时间戳之间的时间差。 |
age(timestamptz) | 从 current_date 相减。 |
date_diff(part, starttimestamptz, endtimestamptz) | starttimestamptz 与 endtimestamptz 之间 part 边界的数量,包含较大的时间戳,不包含较小的时间戳。 |
date_part([part, ...], timestamp) | 将列出的子字段作为 struct 返回。列表必须是常量。 |
date_part(part, timestamp) | 获取子字段(等价于 extract)。 |
date_sub(part, starttimestamptz, endtimestamptz) | starttimestamptz 与 endtimestamptz 之间区间的有符号长度,截断为 part 的整倍数。 |
date_trunc(part, timestamptz) | 按指定精度截断。 |
epoch_ns(timestamptz) | 将 timestamptz 转换为自 epoch 以来的纳秒数。 |
epoch_us(timestamptz) | 将 timestamptz 转换为自 epoch 以来的微秒数。 |
extract(field FROM timestamptz) | 从 TIMESTAMP WITH TIME ZONE 中获取子字段。 |
last_day(timestamptz) | 该月的最后一天。 |
make_timestamptz(bigint, bigint, bigint, bigint, bigint, double, string) | 根据给定部分和时区构造 TIMESTAMP WITH TIME ZONE。 |
make_timestamptz(bigint, bigint, bigint, bigint, bigint, double) | 在当前时区下根据给定部分构造 TIMESTAMP WITH TIME ZONE。 |
make_timestamptz(microseconds) | 根据自 epoch 以来给定的微秒数构造 TIMESTAMP WITH TIME ZONE。 |
strftime(timestamptz, format) | 按格式字符串将 TIMESTAMP WITH TIME ZONE 值转换为字符串。 |
strptime(text, format) | 当指定 %Z 时,按格式字符串将字符串解析为 TIMESTAMP WITH TIME ZONE。 |
time_bucket(bucket_width, timestamptz[, offset]) | 将 timestamptz 截断到宽度为 bucket_width 的网格。当 bucket_width 为月或更粗粒度单位时,网格锚点为 2000-01-01 00:00:00+00:00[ + offset];否则为 2000-01-03 00:00:00+00:00[ + offset]。注意 2000-01-03 是星期一。 |
time_bucket(bucket_width, timestamptz[, origin]) | 将 timestamptz 截断到宽度为 bucket_width 的网格。网格锚定于 origin 时间戳;当 bucket_width 为月或更粗粒度单位时,默认值为 2000-01-01 00:00:00+00:00,否则为 2000-01-03 00:00:00+00:00。注意 2000-01-03 是星期一。 |
time_bucket(bucket_width, timestamptz[, timezone]) | 将 timestamptz 截断到宽度为 bucket_width 的网格。网格锚定于 origin 时间戳;当 bucket_width 为月或更粗粒度单位时,默认值为所提供 timezone 中的 2000-01-01 00:00:00,否则为所提供 timezone 中的 2000-01-03 00:00:00。默认时区为 'UTC'。注意 2000-01-03 是星期一。 |
age(timestamptz, timestamptz)
| 说明 | 参数相减,得到两个时间戳之间的时间差。 |
| 示例 | age(TIMESTAMPTZ '2001-04-10', TIMESTAMPTZ '1992-09-20') |
| 结果 | 8 years 6 months 20 days |
age(timestamptz)
| 说明 | 从 current_date 相减。 |
| 示例 | age(TIMESTAMP '1992-09-20') |
| 结果 | 29 years 1 month 27 days 12:39:00.844 |
date_diff(part, starttimestamptz, endtimestamptz)
| 说明 | starttimestamptz 与 endtimestamptz 之间 part 边界的有符号数量,包含较大的时间戳,不包含较小的时间戳。 |
| 示例 | date_diff('hour', TIMESTAMPTZ '1992-09-30 23:59:59', TIMESTAMPTZ '1992-10-01 01:58:00') |
| 结果 | 2 |
date_part([part, ...], timestamptz)
| 说明 | 将列出的子字段作为 struct 返回。列表必须是常量。 |
| 示例 | date_part(['year', 'month', 'day'], TIMESTAMPTZ '1992-09-20 20:38:40-07') |
| 结果 | {year: 1992, month: 9, day: 20} |
date_part(part, timestamptz)
| 说明 | 获取子字段(等价于 extract)。 |
| 示例 | date_part('minute', TIMESTAMPTZ '1992-09-20 20:38:40') |
| 结果 | 38 |
date_sub(part, starttimestamptz, endtimestamptz)
| 说明 | starttimestamptz 与 endtimestamptz 之间区间的有符号长度,截断为 part 的整倍数。 |
| 示例 | date_sub('hour', TIMESTAMPTZ '1992-09-30 23:59:59', TIMESTAMPTZ '1992-10-01 01:58:00') |
| 结果 | 1 |
date_trunc(part, timestamptz)
| 说明 | 按指定精度截断。 |
| 示例 | date_trunc('hour', TIMESTAMPTZ '1992-09-20 20:38:40') |
| 结果 | 1992-09-20 20:00:00 |
epoch_ns(timestamptz)
| 说明 | 将 timestamptz 转换为自 epoch 以来的纳秒数。 |
| 示例 | epoch_ns('2022-11-07 08:43:04.123456+00'::TIMESTAMPTZ); |
| 结果 | 1667810584123456000 |
epoch_us(timestamptz)
| 说明 | 将 timestamptz 转换为自 epoch 以来的微秒数。 |
| 示例 | epoch_us('2022-11-07 08:43:04.123456+00'::TIMESTAMPTZ); |
| 结果 | 1667810584123456 |
extract(field FROM timestamptz)
| 说明 | 从 TIMESTAMP WITH TIME ZONE 中获取子字段。 |
| 示例 | extract('hour' FROM TIMESTAMPTZ '1992-09-20 20:38:48') |
| 结果 | 20 |
last_day(timestamptz)
| 说明 | 该月的最后一天。 |
| 示例 | last_day(TIMESTAMPTZ '1992-03-22 01:02:03.1234') |
| 结果 | 1992-03-31 |
make_timestamptz(bigint, bigint, bigint, bigint, bigint, double, string)
| 说明 | 根据给定部分和时区构造 TIMESTAMP WITH TIME ZONE。 |
| 示例 | make_timestamptz(1992, 9, 20, 15, 34, 27.123456, 'CET') |
| 结果 | 1992-09-20 06:34:27.123456-07 |
make_timestamptz(bigint, bigint, bigint, bigint, bigint, double)
| 说明 | 在当前时区下根据给定部分构造 TIMESTAMP WITH TIME ZONE。 |
| 示例 | make_timestamptz(1992, 9, 20, 13, 34, 27.123456) |
| 结果 | 1992-09-20 13:34:27.123456-07 |
make_timestamptz(microseconds)
| 说明 | 根据自 epoch 以来给定的微秒数构造 TIMESTAMP WITH TIME ZONE。 |
| 示例 | make_timestamptz(1667810584123456) |
| 结果 | 2022-11-07 16:43:04.123456-08 |
strftime(timestamptz, format)
| 说明 | 按格式字符串将 TIMESTAMP WITH TIME ZONE 值转换为字符串。 |
| 示例 | strftime(timestamptz '1992-01-01 20:38:40', '%a, %-d %B %Y - %I:%M:%S %p') |
| 结果 | Wed, 1 January 1992 - 08:38:40 PM |
strptime(text, format)
| 说明 | 当指定 %Z 时,按格式字符串将字符串解析为 TIMESTAMP WITH TIME ZONE。 |
| 示例 | strptime('Wed, 1 January 1992 - 08:38:40 PST', '%a, %-d %B %Y - %H:%M:%S %Z') |
| 结果 | 1992-01-01 08:38:40-08 |
time_bucket(bucket_width, timestamptz[, offset])
| 说明 | 将 timestamptz 截断到宽度为 bucket_width 的网格。当 bucket_width 为月或更粗粒度单位时,网格锚点为 2000-01-01 00:00:00+00:00[ + offset];否则为 2000-01-03 00:00:00+00:00[ + offset]。注意 2000-01-03 是星期一。 |
| 示例 | time_bucket(INTERVAL '10 minutes', TIMESTAMPTZ '1992-04-20 15:26:00-07', INTERVAL '5 minutes') |
| 结果 | 1992-04-20 15:25:00-07 |
time_bucket(bucket_width, timestamptz[, origin])
| 说明 | 将 timestamptz 截断到宽度为 bucket_width 的网格。网格锚定于 origin 时间戳;当 bucket_width 为月或更粗粒度单位时,默认值为 2000-01-01 00:00:00+00:00,否则为 2000-01-03 00:00:00+00:00。注意 2000-01-03 是星期一。 |
| 示例 | time_bucket(INTERVAL '2 weeks', TIMESTAMPTZ '1992-04-20 15:26:00-07', TIMESTAMPTZ '1992-04-01 00:00:00-07') |
| 结果 | 1992-04-15 00:00:00-07 |
time_bucket(bucket_width, timestamptz[, timezone])
| 说明 | 将 timestamptz 截断到宽度为 bucket_width 的网格。网格锚定于 origin 时间戳;当 bucket_width 为月或更粗粒度单位时,默认值为所提供 timezone 中的 2000-01-01 00:00:00,否则为所提供 timezone 中的 2000-01-03 00:00:00。默认时区为 'UTC'。注意 2000-01-03 是星期一。 |
| 示例 | time_bucket(INTERVAL '2 days', TIMESTAMPTZ '1992-04-20 15:26:00-07', 'Europe/Berlin') |
| 结果 | 1992-04-19 15:00:00-07 (=1992-04-20 00:00:00 Europe/Berlin) |
此外还提供了专门用于提取子字段的函数。
ICU 时间戳表函数
下表展示了 TIMESTAMP WITH TIME ZONE 类型可用的表函数。
| 名称 | 说明 |
|---|---|
generate_series(timestamptz, timestamptz, interval) | 按给定步长在闭区间内生成时间戳表(包含起始和结束时间戳)。 |
range(timestamptz, timestamptz, interval) | 按给定步长在左闭右开区间内生成时间戳表(包含起始时间戳但不包含结束时间戳)。 |
表函数边界不允许使用无穷值。
generate_series(timestamptz, timestamptz, interval)
| 说明 | 按给定步长在闭区间内生成时间戳表(包含起始和结束时间戳)。 |
| 示例 | generate_series(TIMESTAMPTZ '2001-04-10', TIMESTAMPTZ '2001-04-11', INTERVAL 30 MINUTE) |
range(timestamptz, timestamptz, interval)
| 说明 | 按给定步长在左闭右开区间内生成时间戳表(包含起始时间戳但不包含结束时间戳)。 |
| 示例 | range(TIMESTAMPTZ '2001-04-10', TIMESTAMPTZ '2001-04-11', INTERVAL 30 MINUTE) |
ICU 无时区时间戳函数
下表展示了 ICU 提供的、可作用于普通 TIMESTAMP 值的标量函数。
这些函数假设 TIMESTAMP 是“本地时间戳”。
本地时间戳本质上是将某个时区中的各部分值编码到单一值中的方式。
应谨慎使用它们,因为夏令时会导致结果中出现缺口和歧义。
通常,使用 date_part 的 struct 变体可以更可靠地实现相同功能。
| 名称 | 说明 |
|---|---|
current_localtime() | Returns a TIME whose GMT bin values correspond to local time in the current time zone. |
current_localtimestamp() | Returns a TIMESTAMP whose GMT bin values correspond to local date and time in the current time zone. |
localtime | Synonym for the current_localtime() function call. |
localtimestamp | Synonym for the current_localtimestamp() function call. |
timezone(text, timestamp) | Use the date parts of the timestamp in GMT to construct a timestamp in the given time zone. Effectively, the argument is a “local” time. |
timezone(text, timestamptz) | Use the date parts of the timestamp in the given time zone to construct a timestamp. Effectively, the result is a “local” time. |
current_localtime()
| 说明 | Returns a TIME whose GMT bin values correspond to local time in the current time zone. |
| 示例 | current_localtime() |
| 结果 | 08:47:56.497 |
current_localtimestamp()
| 说明 | Returns a TIMESTAMP whose GMT bin values correspond to local date and time in the current time zone. |
| 示例 | current_localtimestamp() |
| 结果 | 2022-12-17 08:47:56.497 |
localtime
| 说明 | Synonym for the current_localtime() function call. |
| 示例 | localtime |
| 结果 | 08:47:56.497 |
localtimestamp
| 说明 | Synonym for the current_localtimestamp() function call. |
| 示例 | localtimestamp |
| 结果 | 2022-12-17 08:47:56.497 |
timezone(text, timestamp)
| 说明 | Use the date parts of the timestamp in GMT to construct a timestamp in the given time zone. Effectively, the argument is a “local” time. |
| 示例 | timezone('America/Denver', TIMESTAMP '2001-02-16 20:38:40') |
| 结果 | 2001-02-16 19:38:40-08 |
timezone(text, timestamptz)
| 说明 | Use the date parts of the timestamp in the given time zone to construct a timestamp. Effectively, the result is a “local” time. |
| 示例 | timezone('America/Denver', TIMESTAMPTZ '2001-02-16 20:38:40-05') |
| 结果 | 2001-02-16 18:38:40 |
At Time Zone
AT TIME ZONE 语法是上文(双参数)timezone 函数的语法糖:
SELECT TIMESTAMP '2001-02-16 20:38:40' AT TIME ZONE 'America/Denver' AS ts;
2001-02-16 19:38:40-08
SELECT TIMESTAMP WITH TIME ZONE '2001-02-16 20:38:40-05' AT TIME ZONE 'America/Denver' AS ts;
2001-02-16 18:38:40
注意,不允许使用数字时区:
SELECT TIMESTAMP '2001-02-16 20:38:40-05' AT TIME ZONE '0200' AS ts;
Not implemented Error: Unknown TimeZone '0200'
Infinities
应用于无穷日期的函数要么返回相同的无穷日期
(例如 greatest),要么返回 NULL(例如 date_part),具体取决于语义是否合理。
通常,如果函数需要检查无穷时间值的组成部分,
the result will be NULL.
Calendars
ICU 扩展还支持非公历日历。 如果当前使用的是此类日历,则显示和分箱操作将使用该日历。