SQLite转DuckDB脚本时遇Timestamp转换错误,求解决方法
解决DuckDB中Windows文件时间转时间戳的问题
你的问题核心是Windows文件时间(SQLite中处理的lastLogon)到DuckDB时间戳的转换逻辑,先理清底层逻辑再修正代码:
背景知识
Windows的lastLogon是从1601-01-01 00:00:00 UTC开始的100纳秒间隔计数,而Unix时间戳是以1970-01-01 00:00:00 UTC为起点的秒数,两者的时间差固定为11644473600秒。
你的错误原因
- 用
epoch_ms(133782998237203223)时,该函数要求传入毫秒级Unix时间戳,但你传入的是Windows的100纳秒计数,数值量级完全不匹配,导致类型转换错误。 - 用
to_timestamp(133782998237203223)时,该函数默认处理秒级Unix时间戳,你传入的数值相当于13万亿秒,远超合理时间范围,自然报错。
正确转换写法
方法1:兼容SQLite逻辑(秒级精度)
直接沿用SQLite的计算逻辑,用DuckDB的to_timestamp函数转换:
SELECT to_timestamp( (lastLogon / 10000000) - 11644473600 ) AS lastLogon;
lastLogon / 10000000:将100纳秒计数转为秒级(1秒=10^7个100纳秒)- 减去
11644473600:将Windows时间起点转为Unix时间起点 to_timestamp():将Unix秒级时间戳转为DuckDB的时间戳类型
方法2:保留亚秒级精度(纳秒级)
如果需要保留更精细的时间精度,可转为纳秒计算后用epoch_ns函数:
SELECT epoch_ns( (lastLogon * 100) - (11644473600 * 1000000000) ) AS lastLogon;
lastLogon * 100:将100纳秒计数转为纯纳秒数11644473600 * 1000000000:将时间差转为纳秒级epoch_ns():将纳秒级Unix时间戳转为时间戳类型
验证示例
用你提供的数值133782998237203223测试:
-- 方法1结果 SELECT to_timestamp( (133782998237203223 / 10000000) - 11644473600 ); -- 输出:2024-04-11 15:57:03.720322 -- 方法2结果 SELECT epoch_ns( (133782998237203223 * 100) - (11644473600 * 1000000000) ); -- 输出:2024-04-11 15:57:03.720322300
内容的提问来源于stack exchange,提问作者user29247426
相关产品推荐
相关产品推荐

