uuid6 / uuid6-ietf-draft

Next Generation UUID Formats
https://datatracker.ietf.org/doc/draft-peabody-dispatch-new-uuid-format/
187 stars 11 forks source link

UUID7 and 128-bit signed integer #15

Closed fabiolimace closed 3 years ago

fabiolimace commented 3 years ago

UUID1 and UUID6 can be used with 128-bit signed integers, but UUID7 cannot.

UUID1 and UUID6 use 60 bits for the timestamp. If the timestamp is unsigned, the maximum possible year is around 5235 AD (2^60/10^7/60/60/24/365.25 + 1582 = ~5235). But the RFC-4122 says that "since a UUID is a fixed size and contains a time field, it is possible for values to rollover around A.D. 3400, depending on the specific algorithm used". It indicates that the timestamp in the RFC-4122 is signed (2^59/10^7/60/60/24/365.25 + 1582 = ~3408).

UUID7 timestamp is a 36 bit unsigned integer. It can contain dates up to 4147 AD (2^36/60/60/24/365.25 + 1970 = ~4147). If a UUID7 is stored in a signed 128-bit integer, it could be sorted incorrectly after 3059 AD (2^35/60/60/24/365.25 + 1970 = ~3059). I think this could be a problem, at least hypothetically.

Some languages and databases have signed and unsigned integer primitives:

But some languages have the signed primitive only:

Rust language has both signed and unsigned 128-bit integers:

There's also an old discussion about 128 primitive in Go: https://github.com/golang/go/issues/9455

bradleypeabody commented 3 years ago

I agree with the analysis but I'm not sure if there is an issue in practice. Since 36 bits is an odd length anyway, in e.g. JavaScript this unsigned value can easily be converted to an int64 or float64 without loss. If the length were longer, such as 64 bits, then I could see a potential problem because valid uint64 values couldn't be represented in e.g. JS. But an unsigned 36-bit integer should be convertible without loss to some 64-bit type in any modern language, afaik.

I'm open to suggestions but I don't see any real benefit in specifying a signed integer option for the timestamp. Let me know if I'm missing something on this.

fabiolimace commented 3 years ago

I was thinking about the future, when (and if) the 128 bit integer primitives become common. If someone decides to store UUID7 as numbers in a hypothetical table field defined as 128 bit signed integer (similar to postgresql's bigint, but twice as big), it's limit could be reached around 3059 AD (2^35bits/60/60/24/365.25 + 1970), instead of 4147 AD (2^36bits/60/60/24/365.25 + 1970).

You are right. It is not an issue at all.

Thanks!