本节介绍用于检查和操作 TIMESTAMP WITH TIME ZONE(或 TIMESTAMPTZ)值的函数和运算符。另请参阅相关的 TIMESTAMP 函数。
时区支持由内置的 ICU 扩展提供。
在下面的示例中,假设当前时区为 America/Los_Angeles(使用公历)。
下表显示了可用于 TIMESTAMPTZ 值的标量函数。由于这些函数不涉及分箱(binning)或显示,因此始终可用。
| 描述 |
当前日期和时间(当前事务的开始时间)。 |
| 示例 |
current_timestamp |
| 结果 |
2022-10-08 12:44:46.122-07 |
| 描述 |
当前日期和时间(当前事务的开始时间)。 |
| 示例 |
get_current_timestamp() |
| 结果 |
2022-10-08 12:44:46.122-07 |
| 描述 |
两个时间戳中较晚的一个。 |
| 示例 |
greatest(TIMESTAMPTZ '1992-09-20 20:38:48', TIMESTAMPTZ '1992-03-22 01:02:03.1234') |
| 结果 |
1992-09-20 20:38:48-07 |
| 描述 |
如果带时区的时间戳是有限的,则返回 true,否则返回 false。 |
| 示例 |
isfinite(TIMESTAMPTZ '1992-03-07') |
| 结果 |
true |
| 描述 |
如果带时区的时间戳是无限的,则返回 true,否则返回 false。 |
| 示例 |
isinf(TIMESTAMPTZ '-infinity') |
| 结果 |
true |
| 描述 |
两个时间戳中较早的一个。 |
| 示例 |
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() |
| 结果 |
2022-10-08 12:44:46.122-07 |
| 描述 |
将 TIME WITH TIME ZONE 转换为 UBIGINT 排序键。 |
| 示例 |
timetz_byte_comparable('18:18:16.21-07:00'::TIMETZ) |
| 结果 |
2494691656335442799 |
| 描述 |
将自纪元以来的秒数转换为带时区的时间戳。 |
| 示例 |
to_timestamp(1284352323.5) |
| 结果 |
2010-09-13 04:32:03.5+00 |
| 描述 |
当前日期和时间(当前事务的开始时间)。 |
| 示例 |
transaction_timestamp() |
| 结果 |
2022-10-08 12:44:46.122-07 |
在未加载时区扩展的情况下,TIMESTAMPTZ 值将使用偏移表示法与字符串进行转换。这使您无需访问时区信息即可正确指定一个瞬时时间。为了可移植性,TIMESTAMPTZ 值将始终使用 GMT 偏移量显示。
SELECT '2022-10-08 13:13:34-07'::TIMESTAMPTZ;
如果加载了诸如 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 值的数学运算符。
| 运算符 |
描述 |
示例 |
结果 |
+ |
添加 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 提供的用于 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_us(timestamptz) |
将 timestamptz 转换为自纪元以来的微秒数。 |
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) |
自纪元以来给定微秒数的 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 '2001-04-10', TIMESTAMPTZ '1992-09-20') |
| 结果 |
8 years 6 months 20 days |
| 描述 |
从 current_date 中减去。 |
| 示例 |
age(TIMESTAMP '1992-09-20') |
| 结果 |
29 years 1 month 27 days 12:39:00.844 |
| 描述 |
starttimestamptz 和 endtimestamptz 之间 part 边界的有符号数量,包含较大的时间戳,排除较小的时间戳。 |
| 示例 |
date_diff('hour', TIMESTAMPTZ '1992-09-30 23:59:59', TIMESTAMPTZ '1992-10-01 01:58:00') |
| 结果 |
2 |
| 描述 |
以 struct 形式获取列出的 子字段。该列表必须是常量。 |
| 示例 |
date_part(['year', 'month', 'day'], TIMESTAMPTZ '1992-09-20 20:38:40-07') |
| 结果 |
{year: 1992, month: 9, day: 20} |
| 描述 |
获取 子字段(等同于 extract)。 |
| 示例 |
date_part('minute', TIMESTAMPTZ '1992-09-20 20:38:40') |
| 结果 |
38 |
| 描述 |
starttimestamptz 和 endtimestamptz 之间的时间间隔的有符号长度,截断为 part 的整数倍。 |
| 示例 |
date_sub('hour', TIMESTAMPTZ '1992-09-30 23:59:59', TIMESTAMPTZ '1992-10-01 01:58:00') |
| 结果 |
1 |
| 描述 |
截断到指定的精度。 |
| 示例 |
date_trunc('hour', TIMESTAMPTZ '1992-09-20 20:38:40') |
| 结果 |
1992-09-20 20:00:00 |
| 描述 |
将 timestamptz 转换为自纪元以来的纳秒数。 |
| 示例 |
epoch_ns('2022-11-07 08:43:04.123456+00'::TIMESTAMPTZ); |
| 结果 |
1667810584123456000 |
| 描述 |
将 timestamptz 转换为自纪元以来的微秒数。 |
| 示例 |
epoch_us('2022-11-07 08:43:04.123456+00'::TIMESTAMPTZ); |
| 结果 |
1667810584123456 |
| 描述 |
从 TIMESTAMP WITH TIME ZONE 中获取 子字段。 |
| 示例 |
extract('hour' FROM TIMESTAMPTZ '1992-09-20 20:38:48') |
| 结果 |
20 |
| 描述 |
月份的最后一天。 |
| 示例 |
last_day(TIMESTAMPTZ '1992-03-22 01:02:03.1234') |
| 结果 |
1992-03-31 |
| 描述 |
给定部分和时区的 TIMESTAMP WITH TIME ZONE。 |
| 示例 |
make_timestamptz(1992, 9, 20, 15, 34, 27.123456, 'CET') |
| 结果 |
1992-09-20 06:34:27.123456-07 |
| 描述 |
当前时区中给定部分的 TIMESTAMP WITH TIME ZONE。 |
| 示例 |
make_timestamptz(1992, 9, 20, 13, 34, 27.123456) |
| 结果 |
1992-09-20 13:34:27.123456-07 |
| 描述 |
自纪元以来给定微秒数的 TIMESTAMP WITH TIME ZONE。 |
| 示例 |
make_timestamptz(1667810584123456) |
| 结果 |
2022-11-07 16:43:04.123456-08 |
| 描述 |
根据格式字符串将 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 |
| 描述 |
如果指定了 %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 |
| 描述 |
将 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 |
| 描述 |
将 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 |
| 描述 |
将 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) |
还有专门的提取函数来获取 子字段。
下表显示了 TIMESTAMP WITH TIME ZONE 类型可用的表函数。
无限值不能用作表函数的边界。
| 描述 |
生成一个闭区间内(包括起始时间和结束时间)的时间戳表,按间隔步进。 |
| 示例 |
generate_series(TIMESTAMPTZ '2001-04-10', TIMESTAMPTZ '2001-04-11', INTERVAL 30 MINUTE) |
| 描述 |
生成一个半开区间内(包括起始时间,但在结束时间之前停止)的时间戳表,按间隔步进。 |
| 示例 |
range(TIMESTAMPTZ '2001-04-10', TIMESTAMPTZ '2001-04-11', INTERVAL 30 MINUTE) |
下表显示了 ICU 提供的对普通 TIMESTAMP 值进行操作的标量函数。这些函数假设 TIMESTAMP 是“本地时间戳”。
本地时间戳实际上是将时区的部分值编码为单个值的一种方式。使用时应谨慎,因为由于夏令时,产生的值可能包含间隙和歧义。通常,使用 date_part 函数的 struct 变体可以更可靠地实现相同的功能。
| 描述 |
返回一个 TIME,其 GMT 分箱值对应于当前时区的本地时间。 |
| 示例 |
current_localtime() |
| 结果 |
08:47:56.497 |
| 描述 |
返回一个 TIMESTAMP,其 GMT 分箱值对应于当前时区的本地日期和时间。 |
| 示例 |
current_localtimestamp() |
| 结果 |
2022-12-17 08:47:56.497 |
| 描述 |
current_localtime() 函数调用的同义词。 |
| 示例 |
localtime |
| 结果 |
08:47:56.497 |
| 描述 |
current_localtimestamp() 函数调用的同义词。 |
| 示例 |
localtimestamp |
| 结果 |
2022-12-17 08:47:56.497 |
| 描述 |
使用 GMT 时间戳的 日期部分 来构建给定时间戳。实际上,参数是“本地”时间。 |
| 示例 |
timezone('America/Denver', TIMESTAMP '2001-02-16 20:38:40') |
| 结果 |
2001-02-16 19:38:40-08 |
| 描述 |
使用给定时区中时间戳的 日期部分 来构建时间戳。实际上,结果是“本地”时间。 |
| 示例 |
timezone('America/Denver', TIMESTAMPTZ '2001-02-16 20:38:40-05') |
| 结果 |
2001-02-16 18:38:40 |
AT TIME ZONE 语法是上面列出的(双参数)timezone 函数的语法糖。
SELECT TIMESTAMP '2001-02-16 20:38:40' AT TIME ZONE 'America/Denver' AS ts;
SELECT TIMESTAMP WITH TIME ZONE '2001-02-16 20:38:40-05' AT TIME ZONE 'America/Denver' AS ts;
请注意,不允许使用数字时区。
SELECT TIMESTAMP '2001-02-16 20:38:40-05' AT TIME ZONE '0200' AS ts;
Not implemented Error: Unknown TimeZone '0200'
应用于无限日期函数的函数将根据“是否有意义”返回相同的无限日期(例如 greatest)或 NULL(例如 date_part)。通常,如果函数需要检查无限时间值的各个部分,结果将为 NULL。
ICU 扩展还支持 非公历日历。如果当前使用的是此类日历,则显示和分箱操作将使用该日历。
© 2025 DuckDB 基金会,阿姆斯特丹,荷兰