单位没有统一标准
应用自带的 SQLite 数据库里,时间列怎么存完全由开发者决定:可能是 10 位 Unix 秒、13 位毫秒、16 位微秒,可能是浏览器内核使用的「自 1601 年起微秒数」,也可能是 ISO 字符串甚至本地时间字符串。贸然按秒换算,会得到 1970 年或几万年后的时间。
先看样本再批量换算
可靠做法分三步:先列出表结构确认哪些列是时间列,再取最新与最旧几行看数值量级与格式,最后用一小批样本验证换算结果是否落在事件时间窗内,确认无误后再对全表执行查询。
基本信息
| 适用平台 | 跨平台(sqlite3 命令行,浏览器与各类应用自带的数据库) |
|---|---|
| 常见单位 | Unix 秒、毫秒、微秒、自 1601 年微秒数、ISO 字符串 |
| 量级识别 | 10 位约为秒、13 位约为毫秒、16 位约为微秒 |
| 查看结构 | sqlite3 数据库文件 ".schema 表名" |
| 换算函数 | datetime(列,'unixepoch'),毫秒与微秒需先除系数 |
典型使用场景
- 浏览器历史与缓存库:还原用户的访问时间分布
- 即时通讯客户端数据库:确定消息收发时刻与联系人顺序
- 应用日志表:把自增 ID 与时间列结合,排出事件先后
- 同步记录表:判断某账号在什么时间产生了活动
- 证据登记:把换算公式与假设写进报告,便于复核者复算
先看样本再换算
先看样本再换算
# 列出表名,确认候选时间列
sqlite3 app.db "SELECT name FROM sqlite_master WHERE type='table';"
sqlite3 app.db ".schema messages"
# 取最新与最旧样例行,看数值量级
sqlite3 app.db "SELECT rowid, ts FROM messages ORDER BY rowid DESC LIMIT 3;"
sqlite3 app.db "SELECT rowid, ts FROM messages ORDER BY rowid ASC LIMIT 3;"
# 确认后换算:10 位按秒,13 位先除 1000
sqlite3 app.db "SELECT datetime(ts,'unixepoch') FROM messages LIMIT 5;"
sqlite3 app.db "SELECT datetime(ts/1000,'unixepoch') FROM messages LIMIT 5;"量级对照与换算
| 数值特征 | 可能的单位 | 换算方式 |
|---|---|---|
| 10 位整数(约 1.7e9) | Unix 秒 | datetime(值,'unixepoch') |
| 13 位整数 | Unix 毫秒 | 先除以 1000 再按秒换算 |
| 16 位整数 | Unix 微秒 | 先除以 1000000 再按秒换算 |
| 17 位整数(约 1.3e16) | 自 1601 年微秒数 | 除以 1000000 后减去 11644473600 秒 |
| 可读字符串 | ISO 或本地时间 | 注意是否带时区偏移 |
不同应用的换算公式不能互相套用:同一个软件的不同版本也可能换过时间单位,取样本的那一步不能省。
字符串形式的时间列要先确认是按本地时间还是 UTC 写入,两者相差一个时区偏移;没有时区信息时必须在报告中写明所采用的假设。