-
Notifications
You must be signed in to change notification settings - Fork 120
Description
Welcome
- Yes, I'm using the latest release.
- Yes, I've searched similar issues on GitHub and didn't find any.
What did you expect to see?
The maximum UUIDv7 should have a timestamp that evaluates to the year 10889 per https://www.rfc-editor.org/rfc/rfc9562.html#section-6.1-2.8
Length:
The length of a given timestamp directly impacts how many timestamp ticks can be contained in a UUID before the maximum value for the timestamp field is reached. Take care to ensure that the proper length is selected for a given timestamp. UUIDv1 and UUIDv6 utilize a 60-bit timestamp valid until 5623 AD; UUIDv7 features a 48-bit timestamp valid until the year 10889 AD.
What did you see instead?
The maximum UUIDv7 had a timestamp that evaluated to the year 2121.
go test -v -timeout 30s -run ^TestTimestampFromV7$ github.com/gofrs/uuid/v5 -race -count=1 -v
=== RUN TestTimestampFromV7
uuid_test.go:275: 1969-12-31 18:00:00 -0600 CST <nil>
uuid_test.go:275: 2023-09-13 14:02:18.605 -0500 CDT <nil>
uuid_test.go:275: 2121-04-11 06:53:25.0117257 -0500 CDT <nil>
--- PASS: TestTimestampFromV7 (0.00s)
PASS
ok github.com/gofrs/uuid/v5 1.194s
This is likely because of inappropriate function re-use between v1 and v7 and an overflow somewhere (though I haven't fully debugged to prove that):
uuid.go:84-67
// Timestamp is the count of 100-nanosecond intervals since 00:00:00.00,
// 15 October 1582 within a V1 UUID. This type has no meaning for other
// UUID versions since they don't have an embedded timestamp.
type Timestamp uint64
const _100nsPerSecond = 10000000
// Time returns the UTC time.Time representation of a Timestamp
func (t Timestamp) Time() (time.Time, error) {
secs := uint64(t) / _100nsPerSecond
nsecs := 100 * (uint64(t) % _100nsPerSecond)
return time.Unix(int64(secs)-(epochStart/_100nsPerSecond), int64(nsecs)), nil
}
Reproduction steps
Simple patch to the existing test file to see the values embedded in already-present tests:
diff --git a/uuid_test.go b/uuid_test.go
index 6dc97f9..7837c45 100644
--- a/uuid_test.go
+++ b/uuid_test.go
@@ -271,6 +271,10 @@ func TestTimestampFromV7(t *testing.T) {
for _, tt := range tests {
got, err := TimestampFromV7(tt.u)
+ if err == nil {
+ t.Log(got.Time())
+ }
+
switch {
case tt.wanterr && err == nil:
t.Errorf("TimestampFromV7(%v) want error, got %v", tt.u, got)
go test -v -timeout 30s -run ^TestTimestampFromV7$ github.com/gofrs/uuid/v5 -race -count=1 -v
=== RUN TestTimestampFromV7
uuid_test.go:275: 1969-12-31 18:00:00 -0600 CST <nil>
uuid_test.go:275: 2023-09-13 14:02:18.605 -0500 CDT <nil>
uuid_test.go:275: 2121-04-11 06:53:25.0117257 -0500 CDT <nil>
--- PASS: TestTimestampFromV7 (0.00s)
PASS
ok github.com/gofrs/uuid/v5 1.194s
Version of flock
N/A
Logs
N/A
Go environment
go version go1.23.3 darwin/arm64
Validation
- Yes, I've included all information above (version, config, etc.).