跳到主要内容
最后 更新

转换为 TIMESTAMP_NS 类型

描述

TIMESTAMP_NS 具有固定纳秒精度,精确取值范围为 [1677-09-21 00:12:43.145224192, 2262-04-11 23:47:16.854775807],不接受精度参数。

字符串和数字通常采用与转换为 DATETIME 相同的字段映射。在严格和非严格 CAST 模式下,TIMESTAMP_NS 支持的字符串格式都与对应模式下的 DATETIME 完全一致。字符串格式能力的唯一区别是 TIMESTAMP_NS 的小数秒精度最高为 9 位,而 DATETIME 最高为 6 位。

语法

CAST(<source_expr> AS TIMESTAMP_NS)
TRY_CAST(<source_expr> AS TIMESTAMP_NS)

支持的源类型

源类型转换行为
CHARVARCHARSTRING按对应的 DATETIME 严格或非严格模式语法解析日期时间,小数秒精度最高为 9 位。
整数类型将数值解释为紧凑日期或日期时间。
FLOAT使用单精度浮点输入实际表示的值;有效数字丢失可能使较大的紧凑日期时间变为非法值。
DOUBLE使用双精度浮点输入实际表示的值;小数部分表示小数秒。
DECIMAL 类型将整数部分解释为紧凑日期或日期时间,将小数部分解释为小数秒。
DATE补充 00:00:00.000000000
DATETIME(p)保留日期时间字段,并在小数部分末尾补零到 9 位。
TIME(p)将输入时长加到当前日期的午夜。
TIMESTAMPTZ(p)将绝对时间转换到当前会话时区,然后移除时区。
TIMESTAMP_NS原值返回。
VARIANT提取兼容的标量值,并应用对应的字符串、数字或时间类型转换规则。
NULL返回 NULL

BOOLEANJSON、IP、二进制和复杂类型等不支持的类型转换时,会在分析阶段失败。这属于类型错误而不是值转换错误,因此非严格模式的 CASTTRY_CAST 都不会将其转换为 NULL

从字符串转换

严格模式

enable_strict_cast = true 时,支持的格式和解析规则与 DATETIME 严格模式的字符串转换完全一致,包括日期和时间字段、两位年份、省略时间字段、连续数字、空白字符以及时区后缀等规则。

非严格模式

enable_strict_cast = false 时,支持的格式和解析规则与 DATETIME 非严格模式的字符串转换完全一致。所有严格模式格式仍然合法,同时也支持 DATETIME 非严格模式允许的额外分隔符、日期时间分隔方式以及首尾空白字符。

两种模式在转换为 TIMESTAMP_NS 时的差异也与 DATETIME 相同:格式错误或值域错误在严格模式下报错,在非严格模式下返回 NULL

小数秒

与对应的 DATETIME 字符串格式相比,唯一区别是支持的小数秒精度:

  • 目标精度固定为 9 位。小数不足 9 位时,在右侧补零。
  • 小数超过 9 位时,按四舍五入规则处理。第 10 位决定第 9 位是否加一,后续数字不影响结果。
  • 小数舍入产生的进位会正常传递到秒、日期或年份。
  • 小数舍入和时区转换完成后,Doris 才检查 TIMESTAMP_NS 的取值范围。

时区处理

TIMESTAMP_NS 不存储时区:

  • 不带时区后缀时,解析得到的日期时间字段保持不变。
  • 带数字偏移、UTC 标识符或 IANA 时区名称时,Doris 将输入的绝对时间转换到当前会话时区,再存储不带时区的日期时间。
  • 值存储后,再修改会话时区不会改变已存储的值。

可接受的时区后缀和时区名称请参见 DATETIME 字符串转换规则时区

以下示例假设 time_zone = '+08:00'

字符串模式结果说明
2024-02-29 12:34:56.123456两种模式2024-02-29 12:34:56.123456000补零到 9 位小数。
2024-02-29 12:34:56.1234567894两种模式2024-02-29 12:34:56.123456789第 10 位小于 5,向下舍入。
2024-02-29 12:34:56.1234567895两种模式2024-02-29 12:34:56.123456790第 10 位等于 5,向上舍入。
2024-02-29 12:34:56.9999999995两种模式2024-02-29 12:34:57.000000000舍入进位到下一秒。
2024-02-29T04:34:56.123456789Z两种模式2024-02-29 12:34:56.123456789从 UTC 转换到会话时区,然后移除时区。
2023-7-4T9-5-3.1Z 仅非严格模式2023-07-04 17:05:03.100000000使用非严格模式的分隔符和首尾空白字符。
2024-02-30 12:34:56两种模式非法公历中不存在 2 月 30 日。
2024-01-01 00:00:00.123.456两种模式非法小数秒语法错误。

边界舍入

最终范围检查在舍入之后进行。因此,紧邻边界之外的输入可能在舍入后变为合法值,而位于上边界的输入也可能因向上舍入而变为非法值。

字符串结果
1677-09-21 00:12:43.1452241914非法:舍入后仍小于下限
1677-09-21 00:12:43.14522419151677-09-21 00:12:43.145224192
2262-04-11 23:47:16.85477580742262-04-11 23:47:16.854775807
2262-04-11 23:47:16.8547758075非法:舍入后大于上限

从数字转换

所有整数、浮点数和小数类型都可以转换为 TIMESTAMP_NS,不支持 BOOLEAN

整数部分的字段映射、两位年份规则和合法的紧凑表示形式与数字转换为 DATETIME相同。具体来说,合法表示包含 3、4、5、6、8 或 14 位整数,小数部分表示小数秒。

紧凑日期时间与小数部分必须组成位于 TIMESTAMP_NS 取值范围内的值。小数秒按照与字符串输入相同的四舍五入规则补齐或舍入到固定 9 位。

从整数类型转换

整数类型没有小数部分。Doris 按照紧凑数字的字段映射进行转换,并在结果末尾补充 .000000000

整数值结果说明
1232000-01-23 00:00:00.0000000003 位紧凑日期。
202402292024-02-29 00:00:00.0000000008 位紧凑日期。
202402291234562024-02-29 12:34:56.00000000014 位紧凑日期时间。
16770921001243非法结果小于下限。
22620412000000非法结果大于上限。

从 FLOAT 转换

转换使用 FLOAT 输入在 CAST 前实际表示的十进制值。单精度浮点数的有效数字通常不足以表示 14 位紧凑日期时间,因此较大的输入可能丢失数字并变成非法日期时间。对于较大的紧凑数值,应使用 DOUBLEDECIMAL

FLOAT 输入表达式严格模式结果非严格模式结果说明
CAST(123 AS FLOAT)2000-01-23 00:00:00.0000000002000-01-23 00:00:00.000000000实际表示的值是精确的。
CAST(20240229123456.125 AS FLOAT)报错NULL有效数字丢失使实际表示的紧凑日期时间变为非法值。

从 DOUBLE 转换

转换使用 DOUBLE 输入在 CAST 前实际表示的十进制值。双精度浮点数可以精确表示所有紧凑 TIMESTAMP_NS 值的 14 位整数部分,但不能用二进制精确表示的小数仍可能在转换前发生舍入。如果需要保留输入的每一位小数,应使用 DECIMAL

DOUBLE 输入表达式结果说明
CAST(20240229123456.125 AS DOUBLE)2024-02-29 12:34:56.125000000整数和小数部分均可精确表示。

从 DECIMAL 转换

DECIMAL 保留字面量的十进制表示。超过纳秒精度的部分按照四舍五入规则舍入到 9 位小数。

DECIMAL 输入表达式结果说明
CAST(20240229123456.1234567895 AS DECIMAL(24, 10))2024-02-29 12:34:56.123456790将小数部分舍入到纳秒。

错误处理

严格和非严格模式采用相同的数字映射。如果实际表示的数值无法得到合法且位于范围内的 TIMESTAMP_NS,严格模式报错,非严格模式返回 NULL。两种模式下输入为 NULL 时均返回 NULL

从日期时间类型转换

从 DATE 转换

Doris 在输入日期后补充 00:00:00.000000000,再检查 TIMESTAMP_NS 的取值范围。由于下边界日期的午夜超出范围,因此 1677-09-21 无法转换;最早可转换的 DATE1677-09-22,最晚是 2262-04-11

输入 DATE结果
1677-09-21非法
1677-09-221677-09-22 00:00:00.000000000
2262-04-112262-04-11 00:00:00.000000000
2262-04-12非法

从 DATETIME 转换

DATETIMETIMESTAMP_NS 都不带时区,因此 Doris 保留日期时间字段,不进行时区调整。DATETIME(p) 的小数在右侧补零到 9 位,不会补充源值中不存在的精度信息。

补零后的结果必须在 TIMESTAMP_NS 范围内。由于 DATETIME 最多支持微秒精度,下边界日期最早可转换的值是 1677-09-21 00:12:43.145225,上边界日期最晚可转换的值是 2262-04-11 23:47:16.854775

输入 DATETIME(6)结果
1677-09-21 00:12:43.145224非法
1677-09-21 00:12:43.1452251677-09-21 00:12:43.145225000
2024-02-29 12:34:56.1234562024-02-29 12:34:56.123456000
2262-04-11 23:47:16.8547752262-04-11 23:47:16.854775000
2262-04-11 23:47:16.854776非法

从 TIME 转换

Doris 从当前会话时区中当前日期的午夜开始,加上带符号的 TIME 时长。该时长可以跨越日期边界。小数部分最多具有微秒精度,转换时在右侧补零到 9 位。最后,Doris 检查得到的日期时间是否在 TIMESTAMP_NS 范围内。

例如,假设当前日期为 2025-04-29

输入 TIME(6)结果
12:34:56.1234562025-04-29 12:34:56.123456000
500:00:00.0000002025-05-19 20:00:00.000000000
-128:00:00.0000002025-04-23 16:00:00.000000000

由于转换结果依赖当前日期,需要可复现的日历日期时,应改用显式的 DATEDATETIME

从 TIMESTAMPTZ 转换

Doris 将输入表示的绝对时间转换到当前会话时区,移除时区,并在源值的小数右侧补零到 9 位。最终得到的本地日期时间必须在 TIMESTAMP_NS 范围内。

因此,修改 time_zone 可能改变转换结果,也可能使边界值移入或移出支持范围。

SET time_zone = '+08:00';
SELECT CAST(CAST('2024-02-29 04:34:56.123456+00:00' AS TIMESTAMPTZ(6)) AS TIMESTAMP_NS) AS ts;
+-------------------------------+
| ts |
+-------------------------------+
| 2024-02-29 12:34:56.123456000 |
+-------------------------------+

从 TIMESTAMP_NS 和 VARIANT 转换

TIMESTAMP_NS 转换为相同类型时,会精确保留原值。VARIANT 中兼容的字符串、数字、日期或时间戳值按照上文对应规则转换。带时区的时间戳值会转换到当前会话时区;不带时区的时间戳值保留日期时间字段。不兼容的 VARIANT 内容根据 CAST 模式返回 NULL 或报错。

相关转换

TIMESTAMP_NS 转换为 DATETIME(p)TIMESTAMPTZ(p) 时,会将小数舍入到目标精度。例如,2024-02-29 12:34:56.123456789 转换为精度 6 后得到 2024-02-29 12:34:56.123457

在比较、Join、CASECOALESCE 或集合运算中混用 TIMESTAMP_NSDATETIME 时,只要能够精确保留各输入值,Doris 会使用 TIMESTAMP_NS 作为公共类型。

错误处理

情况enable_strict_cast = trueenable_strict_cast = falseTRY_CAST
格式或日历值非法报错NULLNULL
超出 TIMESTAMP_NS 取值范围报错NULLNULL
源值为 NULLNULLNULLNULL
不支持的源类型与目标类型组合分析错误分析错误分析错误

对于字符串输入,enable_strict_cast 会选择对应的 DATETIME 严格或非严格解析规则,并控制转换失败的处理方式。对于数字输入,该变量只改变错误处理方式,两种模式使用相同的数字映射。

示例

转换纳秒精度的字符串并观察舍入结果:

SELECT
CAST('2024-02-29 12:34:56.123456' AS TIMESTAMP_NS) AS padded,
CAST('2024-02-29 12:34:56.1234567895' AS TIMESTAMP_NS) AS rounded;
+-------------------------------+-------------------------------+
| padded | rounded |
+-------------------------------+-------------------------------+
| 2024-02-29 12:34:56.123456000 | 2024-02-29 12:34:56.123456790 |
+-------------------------------+-------------------------------+

转换数字形式的日期时间:

SELECT CAST(CAST(20240229123456.1234567895 AS DECIMAL(24, 10)) AS TIMESTAMP_NS) AS ts;
+-------------------------------+
| ts |
+-------------------------------+
| 2024-02-29 12:34:56.123456790 |
+-------------------------------+

非严格模式下,非法值和超出范围的值返回 NULL

SET enable_strict_cast = false;
SELECT
CAST('2024-02-30 00:00:00' AS TIMESTAMP_NS) AS invalid_date,
CAST('2262-04-11 23:47:16.8547758075' AS TIMESTAMP_NS) AS overflow;
+--------------+----------+
| invalid_date | overflow |
+--------------+----------+
| NULL | NULL |
+--------------+----------+