【发布时间】:2021-04-16 20:55:47
【问题描述】:
我需要在 Swift 中生成一个带时间戳的 BSON 格式的对象 ID。 ObjectID 用于 Mongo DB。这如何实现?
【问题讨论】:
我需要在 Swift 中生成一个带时间戳的 BSON 格式的对象 ID。 ObjectID 用于 Mongo DB。这如何实现?
【问题讨论】:
一个简单的解决方案如下所示:
func objectId() -> String {
let time = String(Int(Date().timeIntervalSince1970), radix: 16, uppercase: false)
let machine = String(Int.random(in: 100000 ..< 999999))
let pid = String(Int.random(in: 1000 ..< 9999))
let counter = String(Int.random(in: 100000 ..< 999999))
return time + machine + pid + counter
}
MongoDB docs 指定以下关于 ObjectID 的内容
以上将满足该要求。但是,它只会为时间戳以外的部分生成随机数字字符。一个完美的解决方案是使用诸如 NSProcessInfo 和 NSUUID 之类的 api 用于机器和 pid。它还必须跟踪计数器。
【讨论】:
根据 MongoDB 文档,ObjectId 是使用以下方法生成的:
你可以使用这个类,它实现了上面的。
class ObjectId {
private init() {}
static let shared = ObjectId()
private var counter = Int.random(in: 0...0xffffff)
private func incrementCounter() {
if (counter >= 0xffffff) {
counter = 0
} else {
counter += 1
}
}
func generate() -> String {
let time = ~(~Int(NSDate().timeIntervalSince1970))
let random = Int.random(in: 0...0xffffffffff)
let i = counter
incrementCounter()
var byteArray = Array<UInt8>.init(repeating: 0, count: 12)
byteArray[0] = UInt8((time >> 24) & 0xff)
byteArray[1] = UInt8((time >> 16) & 0xff)
byteArray[2] = UInt8((time >> 8) & 0xff)
byteArray[3] = UInt8(time & 0xff)
byteArray[4] = UInt8((random >> 32) & 0xff)
byteArray[5] = UInt8((random >> 24) & 0xff)
byteArray[6] = UInt8((random >> 16) & 0xff)
byteArray[7] = UInt8((random >> 8) & 0xff)
byteArray[8] = UInt8(random & 0xff)
byteArray[9] = UInt8((i >> 16) & 0xff)
byteArray[10] = UInt8((i >> 8) & 0xff)
byteArray[11] = UInt8(i & 0xff)
let id = byteArray
.map({ String($0, radix: 16, uppercase: false)
.padding(toLength: 2, withPad: "0", startingAt: 0) })
.joined()
return id
}
}
以下代码将生成一个新的 ObjectId 字符串:
ObjectId.shared.generate()
【讨论】: