You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Room库中strftime与datetime使用异常:查询年份月份始终为0

解决SQLite查询中时间戳转年、月始终为0的问题

这个问题我之前也碰到过,核心原因是SQLite的datetime()函数对整数型时间戳的解析规则和你存储的毫秒级时间戳不兼容,导致提取的年、月始终为0,下面给你详细分析和解决方案:

问题根源

你通过@TypeConverter把GregorianCalendar转成了毫秒级的Long型时间戳(比如1422634536401)存在数据库里,但SQLite的datetime()函数默认对整数参数的处理是:

把整数当作秒级的Unix时间戳(从1970-01-01 00:00:00 UTC开始的秒数)

直接用datetime(date)时,SQLite会把你的毫秒数当成秒数解析,得到的是一个远超常规范围的日期,自然提取不出正确的年、月,最终返回0。

解决方案:修正SQL查询语句

你需要把毫秒级时间戳除以1000转成秒级,同时加上unixepoch修饰符明确告诉SQLite这是Unix时间戳,修改后的查询语句如下:

获取最后一条记录的查询

@Query("SELECT *, CAST(strftime('%Y', datetime(date / 1000, 'unixepoch')) AS int) AS year, CAST(strftime('%m', datetime(date / 1000, 'unixepoch')) AS int) AS month FROM memo ORDER BY date DESC LIMIT 1")
MemoWithTimestamp getTheLastMemo();

获取第一条记录的查询

@Query("SELECT *, CAST(strftime('%Y', datetime(date / 1000, 'unixepoch')) AS int) AS year, CAST(strftime('%m', datetime(date / 1000, 'unixepoch')) AS int) AS month FROM memo ORDER BY date ASC LIMIT 1")
MemoWithTimestamp getTheFirstMemo();

补充说明

  • 为什么要加unixepoch?如果不加,SQLite会把整数当作儒略日(一种古老的日期计算方式),还是会解析错误,必须用unixepoch指定这是Unix时间戳格式。
  • 如果你不需要毫秒级精度,也可以修改Converters类,直接存储秒级时间戳(calendar.getTimeInMillis() / 1000),这样查询时就不用除以1000,但会丢失毫秒信息,按需选择即可。
  • 你的MemoWithTimestamp类的字段别名和查询结果的别名是匹配的(year、month),这部分不需要修改。

内容的提问来源于stack exchange,提问作者cmingmai

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:34:49