Skip to content

Commit 22c52c2

Browse files
authored
implement TimestampFromV7 (#125)
closes #123
1 parent 8318aa5 commit 22c52c2

File tree

2 files changed

+51
-0
lines changed

2 files changed

+51
-0
lines changed

uuid.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,32 @@ func TimestampFromV6(u UUID) (Timestamp, error) {
131131
return Timestamp(uint64(low) + (uint64(mid) << 12) + (uint64(hi) << 28)), nil
132132
}
133133

134+
// TimestampFromV7 returns the Timestamp embedded within a V7 UUID. This
135+
// function returns an error if the UUID is any version other than 7.
136+
//
137+
// This is implemented based on revision 03 of the Peabody UUID draft, and may
138+
// be subject to change pending further revisions. Until the final specification
139+
// revision is finished, changes required to implement updates to the spec will
140+
// not be considered a breaking change. They will happen as a minor version
141+
// releases until the spec is final.
142+
func TimestampFromV7(u UUID) (Timestamp, error) {
143+
if u.Version() != 7 {
144+
return 0, fmt.Errorf("uuid: %s is version %d, not version 6", u, u.Version())
145+
}
146+
147+
t := 0 |
148+
(int64(u[0]) << 40) |
149+
(int64(u[1]) << 32) |
150+
(int64(u[2]) << 24) |
151+
(int64(u[3]) << 16) |
152+
(int64(u[4]) << 8) |
153+
int64(u[5])
154+
155+
// convert to format expected by Timestamp
156+
tsNanos := epochStart + time.UnixMilli(t).UTC().UnixNano()/100
157+
return Timestamp(tsNanos), nil
158+
}
159+
134160
// Nil is the nil UUID, as specified in RFC-4122, that has all 128 bits set to
135161
// zero.
136162
var Nil = UUID{}

uuid_test.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,31 @@ func TestTimestampFromV6(t *testing.T) {
256256
}
257257
}
258258

259+
func TestTimestampFromV7(t *testing.T) {
260+
tests := []struct {
261+
u UUID
262+
want Timestamp
263+
wanterr bool
264+
}{
265+
{u: Must(NewV1()), wanterr: true},
266+
// v7 is unix_ts_ms, so zero value time is unix epoch
267+
{u: Must(FromString("00000000-0000-7000-0000-000000000000")), want: 122192928000000000},
268+
{u: Must(FromString("018a8fec-3ced-7164-995f-93c80cbdc575")), want: 139139245386050000},
269+
{u: Must(FromString("ffffffff-ffff-7fff-ffff-ffffffffffff")), want: Timestamp(epochStart + time.UnixMilli((1<<48)-1).UTC().UnixNano()/100)},
270+
}
271+
for _, tt := range tests {
272+
got, err := TimestampFromV7(tt.u)
273+
274+
switch {
275+
case tt.wanterr && err == nil:
276+
t.Errorf("TimestampFromV7(%v) want error, got %v", tt.u, got)
277+
278+
case tt.want != got:
279+
t.Errorf("TimestampFromV7(%v) got %v, want %v", tt.u, got, tt.want)
280+
}
281+
}
282+
}
283+
259284
func BenchmarkFormat(b *testing.B) {
260285
var tests = []string{
261286
"%s",

0 commit comments

Comments
 (0)