@@ -262,11 +262,14 @@ func TestTimestampFromV7(t *testing.T) {
262
262
want Timestamp
263
263
wanterr bool
264
264
}{
265
+ // These non-V7 versions should not be able to be provided to TimestampFromV7
265
266
{u : Must (NewV1 ()), wanterr : true },
267
+ {u : NewV3 (NamespaceDNS , "a.example.com" ), wanterr : true },
266
268
// v7 is unix_ts_ms, so zero value time is unix epoch
267
269
{u : Must (FromString ("00000000-0000-7000-0000-000000000000" )), want : 122192928000000000 },
268
270
{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 )},
271
+ // Calculated as `(1<<48)-1` milliseconds, times 100 ns per ms, plus epoch offset from 1970 to 1582.
272
+ {u : Must (FromString ("ffffffff-ffff-7fff-bfff-ffffffffffff" )), want : 2936942695106550000 },
270
273
}
271
274
for _ , tt := range tests {
272
275
got , err := TimestampFromV7 (tt .u )
@@ -281,6 +284,56 @@ func TestTimestampFromV7(t *testing.T) {
281
284
}
282
285
}
283
286
287
+ func TestMinMaxTimestamps (t * testing.T ) {
288
+ tests := []struct {
289
+ u UUID
290
+ want time.Time
291
+ }{
292
+
293
+ // v1 min and max
294
+ {u : Must (FromString ("00000000-0000-1000-8000-000000000000" )), want : time .Date (1582 , 10 , 15 , 0 , 0 , 0 , 0 , time .UTC )}, //1582-10-15 0:00:00 (UTC)
295
+ {u : Must (FromString ("ffffffff-ffff-1fff-bfff-ffffffffffff" )), want : time .Date (5236 , 3 , 31 , 21 , 21 , 00 , 684697500 , time .UTC )}, //5236-03-31 21:21:00 (UTC)
296
+
297
+ // v6 min and max
298
+ {u : Must (FromString ("00000000-0000-6000-8000-000000000000" )), want : time .Date (1582 , 10 , 15 , 0 , 0 , 0 , 0 , time .UTC )}, //1582-10-15 0:00:00 (UTC)
299
+ {u : Must (FromString ("ffffffff-ffff-6fff-bfff-ffffffffffff" )), want : time .Date (5236 , 3 , 31 , 21 , 21 , 00 , 684697500 , time .UTC )}, //5236-03-31 21:21:00 (UTC)
300
+
301
+ // v7 min and max
302
+ {u : Must (FromString ("00000000-0000-7000-8000-000000000000" )), want : time .Date (1970 , 1 , 1 , 0 , 0 , 0 , 0 , time .UTC )}, //1970-01-01 0:00:00 (UTC)
303
+ {u : Must (FromString ("ffffffff-ffff-7fff-bfff-ffffffffffff" )), want : time .Date (10889 , 8 , 2 , 5 , 31 , 50 , 655000000 , time .UTC )}, //10889-08-02 5:31:50.655 (UTC)
304
+ }
305
+ for _ , tt := range tests {
306
+ var got Timestamp
307
+ var err error
308
+ var functionName string
309
+
310
+ switch tt .u .Version () {
311
+ case V1 :
312
+ functionName = "TimestampFromV1"
313
+ got , err = TimestampFromV1 (tt .u )
314
+ case V6 :
315
+ functionName = "TimestampFromV6"
316
+ got , err = TimestampFromV6 (tt .u )
317
+ case V7 :
318
+ functionName = "TimestampFromV7"
319
+ got , err = TimestampFromV7 (tt .u )
320
+ }
321
+
322
+ if err != nil {
323
+ t .Errorf (functionName + "(%v) got error %v, want %v" , tt .u , err , tt .want )
324
+ }
325
+
326
+ tm , err := got .Time ()
327
+ if err != nil {
328
+ t .Errorf (functionName + "(%v) got error %v, want %v" , tt .u , err , tt .want )
329
+ }
330
+
331
+ if ! tt .want .Equal (tm ) {
332
+ t .Errorf (functionName + "(%v) got %v, want %v" , tt .u , tm .UTC (), tt .want )
333
+ }
334
+ }
335
+ }
336
+
284
337
func BenchmarkFormat (b * testing.B ) {
285
338
var tests = []string {
286
339
"%s" ,
@@ -300,3 +353,90 @@ func BenchmarkFormat(b *testing.B) {
300
353
})
301
354
}
302
355
}
356
+
357
+ var uuidBenchmarkSink UUID
358
+ var timestampBenchmarkSink Timestamp
359
+ var timeBenchmarkSink time.Time
360
+
361
+ func BenchmarkTimestampFrom (b * testing.B ) {
362
+ var err error
363
+ numbUUIDs := 1000
364
+ if testing .Short () {
365
+ numbUUIDs = 10
366
+ }
367
+
368
+ funcs := []struct {
369
+ name string
370
+ create func () (UUID , error )
371
+ timestamp func (UUID ) (Timestamp , error )
372
+ }{
373
+ {"v1" , NewV1 , TimestampFromV1 },
374
+ {"v6" , NewV6 , TimestampFromV6 },
375
+ {"v7" , NewV7 , TimestampFromV7 },
376
+ }
377
+
378
+ for _ , fns := range funcs {
379
+ b .Run (fns .name , func (b * testing.B ) {
380
+ // Make sure we don't just encode the same string over and over again as that will hit memory caches unrealistically
381
+ uuids := make ([]UUID , numbUUIDs )
382
+ for i := 0 ; i < numbUUIDs ; i ++ {
383
+ uuids [i ] = Must (fns .create ())
384
+ if ! testing .Short () {
385
+ time .Sleep (1 * time .Millisecond )
386
+ }
387
+ }
388
+ b .ResetTimer ()
389
+ for i := 0 ; i < b .N ; i ++ {
390
+ timestampBenchmarkSink , err = fns .timestamp (uuids [i % numbUUIDs ])
391
+
392
+ if err != nil {
393
+ b .Fatal (err )
394
+ }
395
+ }
396
+ })
397
+ }
398
+ }
399
+
400
+ func BenchmarkTimestampTime (b * testing.B ) {
401
+ var err error
402
+ numbUUIDs := 1000
403
+ if testing .Short () {
404
+ numbUUIDs = 10
405
+ }
406
+
407
+ funcs := []struct {
408
+ name string
409
+ create func () (UUID , error )
410
+ timestamp func (UUID ) (Timestamp , error )
411
+ }{
412
+ {"v1" , NewV1 , TimestampFromV1 },
413
+ {"v6" , NewV6 , TimestampFromV6 },
414
+ {"v7" , NewV7 , TimestampFromV7 },
415
+ }
416
+
417
+ for _ , fns := range funcs {
418
+ b .Run (fns .name , func (b * testing.B ) {
419
+ // Make sure we don't just encode the same string over and over again as that will hit memory caches unrealistically
420
+ uuids := make ([]UUID , numbUUIDs )
421
+ timestamps := make ([]Timestamp , numbUUIDs )
422
+ for i := 0 ; i < numbUUIDs ; i ++ {
423
+ uuids [i ] = Must (fns .create ())
424
+ timestamps [i ], err = fns .timestamp (uuids [i ])
425
+ if err != nil {
426
+ b .Fatal (err )
427
+ }
428
+ if ! testing .Short () {
429
+ time .Sleep (1 * time .Millisecond )
430
+ }
431
+ }
432
+ b .ResetTimer ()
433
+ for i := 0 ; i < b .N ; i ++ {
434
+ timeBenchmarkSink , err = timestamps [i % numbUUIDs ].Time ()
435
+ if err != nil {
436
+ b .Fatal (err )
437
+ }
438
+ }
439
+ })
440
+ }
441
+
442
+ }
0 commit comments