如何使用负时间值构造MongoDB的ObjectId?
问题描述
测试代码及运行结果:
const { ObjectId } = require("mongodb"); > new Date(-1) 1969-12-31T23:59:59.999Z > ObjectId(-1) Uncaught: RangeError [ERR_OUT_OF_RANGE]: The value of "value" is out of range. It must be >= 0 and <= 4294967295. Received -1
补充测试:
> new Date(0) 1970-01-01T00:00:00.000Z > new Date(4294967294) 1970-02-19T17:02:47.294Z
疑问:为何用负时间值构造MongoDB的ObjectId会触发范围错误,且输入时间值被限制在>=0且<=4294967295?
原因解析
MongoDB的ObjectId是固定12字节的结构化标识符,它的时间相关部分有明确的底层限制:
- ObjectId的前4字节是无符号32位整数类型的时间戳,这个时间戳记录的是从UTC时间1970-01-01 00:00:00开始流逝的秒数
- 无符号32位整数的取值范围天然就是
0到2^32-1(也就是4294967295),它无法存储负数,也不能超过最大值
这里需要注意:你测试里用new Date(4294967294)传入的是毫秒数,所以对应的是1970年2月的时间;但ObjectId的时间戳是秒数,4294967295秒换算成毫秒是4294967295000,对应的实际时间是2106年2月左右,这才是ObjectId时间戳的上限。
当你尝试用-1构造ObjectId时,驱动会把这个值当作时间戳的数值来处理,但负数不符合无符号32位整数的要求,因此直接触发范围错误。
内容的提问来源于stack exchange,提问作者Bear Bile Farming is Torture
相关产品推荐
相关产品推荐

