Oracle:将 DateTime 转换为 Epoch 时出错
Oracle: Error in converting DateTime to Epoch
尝试将日期时间转换为纪元时,出现错误:ORA-01810:格式代码出现两次
QracleSQL 查询:
select (trunc(TO_TIMESTAMP('2022-05-08T19:09:17Z', 'yyyy-MM-dd"T"HH:mm:ssXXX')) - TO_DATE('01/01/1970', 'MM/DD/YYYY')) * 24 * 60 * 60 from dual;
像这样:
测试数据
create table sample_inputs (ts_string) as
select '2022-05-08T16:49:34Z' from dual union all
select '2022-04-15T04:20:13.525Z' from dual
;
查询和输出
with
prep (ts_string, ts) as (
select ts_string,
to_timestamp(ts_string, 'yyyy-mm-dd"T"hh24:mi:ss.ff"Z"')
from sample_inputs
)
select ts_string,
round((trunc(ts, 'mi') - date '1970-01-01') * 24 * 3600)
+ extract(second from ts)
as epoch
from prep;
TS_STRING EPOCH
-------------------------- -----------
2022-05-08T16:49:34Z 1652028574
2022-04-15T04:20:13.525Z 1649996413.525
备注
在你的尝试中有几个错误。 Oracle fractional-seconds 元素是 ff
,而不是 xxx
。您在末尾缺少 hard-coded Z 的占位符(掩码中有“T”,这是正确的,但您缺少类似的“Z”)。 HH
是不够的 - 它必须是 HH24
或 HH
,最后是 AM
(或等效的 PM
)。在你的例子中,它显然是 HH24
。 MM
和 mm
在 Oracle 中意味着同样的事情——这不是 Unix。分钟的元素是 mi
或等效的 MI
.
我写的查询在纪元中保留小数秒。今天早些时候的另一个问题(也许你也是,在另一个用户名下)被关闭为“重复” - 但声称的“重复”与保留小数秒完全无关,当输入是 Oracle 时间戳与 Oracle 日期(哪个总是有时间成分,但只有整秒)。
你应该使用:
TO_TIMESTAMP_TZ
而不是 TO_TIMESTAMP
- 格式模型
YYYY-MM-DD"T"HH24:MI:SS.FF TZD
而不是错误地使用 MM
两次,HH24
而不是 HH
,.FF
而不是 XXX
,和 TZD
而不是硬编码 "Z"
.
- 确保您始终将时间戳转换为 UTC 时区(您的已经是,但其他人可能不是)
- 不要
TRUNC
在午夜将时间戳设为 DATE
,否则您将丢失时间部分。
像这样:
SELECT ROUND(
(
TRUNC(timestamp_value AT TIME ZONE 'UTC', 'MI')
- DATE '1970-01-01'
) * 86400
+ EXTRACT(SECOND FROM timestamp_value AT TIME ZONE 'UTC')
) AS epoch_time
FROM (
SELECT TO_TIMESTAMP_TZ(
'2022-05-08T19:09:17Z',
'YYYY-MM-DD"T"HH24:MI:SS.FF TZD'
) AS timestamp_value
FROM DUAL
);
输出:
EPOCH_TIME
1652033357
db<>fiddle here
尝试将日期时间转换为纪元时,出现错误:ORA-01810:格式代码出现两次
QracleSQL 查询:
select (trunc(TO_TIMESTAMP('2022-05-08T19:09:17Z', 'yyyy-MM-dd"T"HH:mm:ssXXX')) - TO_DATE('01/01/1970', 'MM/DD/YYYY')) * 24 * 60 * 60 from dual;
像这样:
测试数据
create table sample_inputs (ts_string) as
select '2022-05-08T16:49:34Z' from dual union all
select '2022-04-15T04:20:13.525Z' from dual
;
查询和输出
with
prep (ts_string, ts) as (
select ts_string,
to_timestamp(ts_string, 'yyyy-mm-dd"T"hh24:mi:ss.ff"Z"')
from sample_inputs
)
select ts_string,
round((trunc(ts, 'mi') - date '1970-01-01') * 24 * 3600)
+ extract(second from ts)
as epoch
from prep;
TS_STRING EPOCH
-------------------------- -----------
2022-05-08T16:49:34Z 1652028574
2022-04-15T04:20:13.525Z 1649996413.525
备注
在你的尝试中有几个错误。 Oracle fractional-seconds 元素是 ff
,而不是 xxx
。您在末尾缺少 hard-coded Z 的占位符(掩码中有“T”,这是正确的,但您缺少类似的“Z”)。 HH
是不够的 - 它必须是 HH24
或 HH
,最后是 AM
(或等效的 PM
)。在你的例子中,它显然是 HH24
。 MM
和 mm
在 Oracle 中意味着同样的事情——这不是 Unix。分钟的元素是 mi
或等效的 MI
.
我写的查询在纪元中保留小数秒。今天早些时候的另一个问题(也许你也是,在另一个用户名下)被关闭为“重复” - 但声称的“重复”与保留小数秒完全无关,当输入是 Oracle 时间戳与 Oracle 日期(哪个总是有时间成分,但只有整秒)。
你应该使用:
TO_TIMESTAMP_TZ
而不是TO_TIMESTAMP
- 格式模型
YYYY-MM-DD"T"HH24:MI:SS.FF TZD
而不是错误地使用MM
两次,HH24
而不是HH
,.FF
而不是XXX
,和TZD
而不是硬编码"Z"
. - 确保您始终将时间戳转换为 UTC 时区(您的已经是,但其他人可能不是)
- 不要
TRUNC
在午夜将时间戳设为DATE
,否则您将丢失时间部分。
像这样:
SELECT ROUND(
(
TRUNC(timestamp_value AT TIME ZONE 'UTC', 'MI')
- DATE '1970-01-01'
) * 86400
+ EXTRACT(SECOND FROM timestamp_value AT TIME ZONE 'UTC')
) AS epoch_time
FROM (
SELECT TO_TIMESTAMP_TZ(
'2022-05-08T19:09:17Z',
'YYYY-MM-DD"T"HH24:MI:SS.FF TZD'
) AS timestamp_value
FROM DUAL
);
输出:
EPOCH_TIME 1652033357
db<>fiddle here