在Rails中如何将MongoDB ObjectID转时间戳?如何不使用getTimestamp()转MongoDB ID为日期?
嘿,这个问题我太熟了!MongoDB的ObjectID结构里,前4个字节本身就是文档创建时的Unix时间戳(秒级),所以咱们完全可以用Ruby/Rails的原生方法来解析,根本不需要依赖JavaScript的getTimestamp()。下面分两种场景给你具体实现:
1. 将MongoDB ObjectID转换为时间戳
不管你的ObjectID是字符串形式,还是Mongoid里的BSON::ObjectId实例,都能轻松拿到时间戳:
场景1:ObjectID是字符串
直接截取前8个十六进制字符(对应前4个字节),然后转成十进制整数就是Unix时间戳(秒级):
# 示例ObjectID字符串 object_id_str = "60d21b4667d0d8992e610c85" # 截取前8位,转成16进制到十进制 timestamp = object_id_str[0..7].to_i(16) # 输出结果:1624365894(对应2021-06-22左右的时间)
场景2:ObjectID是BSON::ObjectId实例
如果是Mongoid模型返回的_id(本身就是BSON::ObjectId对象),可以直接操作字节数组:
# 从字符串生成ObjectID实例(或者直接用模型的user._id) object_id = BSON::ObjectId.from_string("60d21b4667d0d8992e610c85") # 取前4个字节,转成大端序整数 timestamp = object_id.bytes[0..3].pack("C*").unpack1("N") # 同样得到秒级时间戳:1624365894
2. 将MongoDB ObjectID转换为对应的日期
拿到时间戳之后,转日期就简单了,用Rails/Ruby的时间处理方法就行,还能轻松适配时区:
# 用本地时区生成Time对象 local_time = Time.at(timestamp) # 用Rails配置的时区生成Time对象(推荐在Rails项目中用这个) zone_time = Time.zone.at(timestamp) # 转成DateTime对象 datetime = DateTime.strptime(timestamp.to_s, "%s")
也可以把两步合并,直接从ObjectID转日期:
object_id_str = "60d21b4667d0d8992e610c85" created_at = Time.zone.at(object_id_str[0..7].to_i(16)) # 输出类似:Wed, 22 Jun 2021 15:24:54 UTC +00:00(根据你的时区配置变化)
小提醒
MongoDB ObjectID的时间戳只有秒级精度,没法拿到毫秒哦,这是它的结构决定的。
内容的提问来源于stack exchange,提问作者Jon Kern




