From 774342570aeeb24fd2964e898cbdab01b1468ae2 Mon Sep 17 00:00:00 2001 From: Yoshiyuki Mineo Date: Wed, 7 May 2025 13:17:30 +0900 Subject: [PATCH] Add Compose method (#71) --- v2/sonyflake.go | 11 +++++ v2/sonyflake_test.go | 100 ++++++++++++++++++++++++++++++++++++------- 2 files changed, 95 insertions(+), 16 deletions(-) diff --git a/v2/sonyflake.go b/v2/sonyflake.go index e6ab73a..244e1dd 100644 --- a/v2/sonyflake.go +++ b/v2/sonyflake.go @@ -252,6 +252,17 @@ func (sf *Sonyflake) ToTime(id int64) time.Time { return time.Unix(0, (sf.startTime+sf.timePart(id))*sf.timeUnit) } +// Compose creates a Sonyflake ID from its components. +// The time parameter should be the time when the ID was generated. +// The sequence parameter should be between 0 and 2^BitsSequence-1 (inclusive). +// The machineID parameter should be between 0 and 2^BitsMachineID-1 (inclusive). +func (sf *Sonyflake) Compose(t time.Time, sequence, machineID int) int64 { + elapsedTime := sf.toInternalTime(t.UTC()) - sf.startTime + return elapsedTime<<(sf.bitsSequence+sf.bitsMachine) | + int64(sequence)<= time.Duration(sf.timeUnit) { - t.Errorf("unexpected time: %v", tm) - } -} - func TestPrivateIPv4(t *testing.T) { testCases := []struct { description string @@ -351,3 +335,87 @@ func TestLower16BitPrivateIP(t *testing.T) { }) } } + +func TestToTime(t *testing.T) { + start := time.Now() + sf := newSonyflake(t, Settings{ + TimeUnit: time.Millisecond, + StartTime: start, + }) + + id := nextID(t, sf) + + tm := sf.ToTime(id) + diff := tm.Sub(start) + if diff < 0 || diff >= time.Duration(sf.timeUnit) { + t.Errorf("unexpected time: %v", tm) + } +} + +func TestComposeAndDecompose(t *testing.T) { + now := time.Now() + sf := newSonyflake(t, Settings{ + TimeUnit: time.Millisecond, + StartTime: now, + }) + + testCases := []struct { + name string + time time.Time + sequence int + machineID int + }{ + { + name: "zero values", + time: now, + sequence: 0, + machineID: 0, + }, + { + name: "max sequence", + time: now, + sequence: 1<