diff --git a/sonyflake.go b/sonyflake.go index b316924..ebafa46 100644 --- a/sonyflake.go +++ b/sonyflake.go @@ -117,8 +117,8 @@ func currentElapsedTime(startTime int64) int64 { } func sleepTime(overtime int64) time.Duration { - return time.Duration(overtime)*10*time.Millisecond - - time.Duration(time.Now().UTC().UnixNano()%sonyflakeTimeUnit)*time.Nanosecond + return time.Duration(overtime*sonyflakeTimeUnit) - + time.Duration(time.Now().UTC().UnixNano()%sonyflakeTimeUnit) } func (sf *Sonyflake) toID() (uint64, error) { @@ -165,15 +165,33 @@ func lower16BitPrivateIP() (uint16, error) { return uint16(ip[2])<<8 + uint16(ip[3]), nil } +// ElapsedTime returns the elapsed time when the given Sonyflake ID was generated. +func ElapsedTime(id uint64) time.Duration { + return time.Duration(elapsedTime(id) * sonyflakeTimeUnit) +} + +func elapsedTime(id uint64) uint64 { + return id >> (BitLenSequence + BitLenMachineID) +} + +// SequenceNumber returns the sequence number of a Sonyflake ID. +func SequenceNumber(id uint64) uint64 { + const maskSequence = uint64((1<> BitLenMachineID +} + +// MachineID returns the machine ID of a Sonyflake ID. +func MachineID(id uint64) uint64 { + const maskMachineID = uint64(1<> 63 - time := id >> (BitLenSequence + BitLenMachineID) - sequence := id & maskSequence >> BitLenMachineID - machineID := id & maskMachineID + time := elapsedTime(id) + sequence := SequenceNumber(id) + machineID := MachineID(id) return map[string]uint64{ "id": id, "msb": msb, diff --git a/sonyflake_test.go b/sonyflake_test.go index a52476f..f7fed6e 100644 --- a/sonyflake_test.go +++ b/sonyflake_test.go @@ -36,34 +36,28 @@ func nextID(t *testing.T) uint64 { } func TestSonyflakeOnce(t *testing.T) { - sleepTime := uint64(50) - time.Sleep(time.Duration(sleepTime) * 10 * time.Millisecond) + sleepTime := time.Duration(50 * sonyflakeTimeUnit) + time.Sleep(sleepTime) id := nextID(t) - parts := Decompose(id) - actualMSB := parts["msb"] - if actualMSB != 0 { - t.Errorf("unexpected msb: %d", actualMSB) - } - - actualTime := parts["time"] - if actualTime < sleepTime || actualTime > sleepTime+1 { + actualTime := ElapsedTime(id) + if actualTime < sleepTime || actualTime > sleepTime+sonyflakeTimeUnit { t.Errorf("unexpected time: %d", actualTime) } - actualSequence := parts["sequence"] + actualSequence := SequenceNumber(id) if actualSequence != 0 { t.Errorf("unexpected sequence: %d", actualSequence) } - actualMachineID := parts["machine-id"] + actualMachineID := MachineID(id) if actualMachineID != machineID { t.Errorf("unexpected machine id: %d", actualMachineID) } fmt.Println("sonyflake id:", id) - fmt.Println("decompose:", parts) + fmt.Println("decompose:", Decompose(id)) } func currentTime() int64 { @@ -187,3 +181,9 @@ func TestNextIDError(t *testing.T) { t.Errorf("time is not over") } } + +func TestSonyflakeTimeUnit(t *testing.T) { + if time.Duration(sonyflakeTimeUnit) != 10*time.Millisecond { + t.Errorf("unexpected time unit") + } +}