瀏覽代碼

Add TimeUUIDWith function (#1029)

TimeUUIDWith is a function that generates a Version 1 UUID
with given parameters.
Yasuharu Goto 8 年之前
父節點
當前提交
9ce8b08dfa
共有 2 個文件被更改,包括 49 次插入4 次删除
  1. 25 4
      uuid.go
  2. 24 0
      uuid_test.go

+ 25 - 4
uuid.go

@@ -122,19 +122,29 @@ func TimeUUID() UUID {
 // RFC 4122. This UUID contains the MAC address of the node that generated
 // the UUID, the given timestamp and a sequence number.
 func UUIDFromTime(aTime time.Time) UUID {
+	utcTime := aTime.In(time.UTC)
+	t := int64(utcTime.Unix()-timeBase)*10000000 + int64(utcTime.Nanosecond()/100)
+	clock := atomic.AddUint32(&clockSeq, 1)
+
+	return TimeUUIDWith(t, clock, hardwareAddr)
+}
+
+// TimeUUIDWith generates a new time based UUID (version 1) as described in
+// RFC4122 with given parameters. t is the number of 100's of nanoseconds
+// since 15 Oct 1582 (60bits). clock is the number of clock sequence (14bits).
+// node is a slice to gurarantee the uniqueness of the UUID (up to 6bytes).
+// Note: calling this function does not increment the static clock sequence.
+func TimeUUIDWith(t int64, clock uint32, node []byte) UUID {
 	var u UUID
 
-	utcTime := aTime.In(time.UTC)
-	t := uint64(utcTime.Unix()-timeBase)*10000000 + uint64(utcTime.Nanosecond()/100)
 	u[0], u[1], u[2], u[3] = byte(t>>24), byte(t>>16), byte(t>>8), byte(t)
 	u[4], u[5] = byte(t>>40), byte(t>>32)
 	u[6], u[7] = byte(t>>56)&0x0F, byte(t>>48)
 
-	clock := atomic.AddUint32(&clockSeq, 1)
 	u[8] = byte(clock >> 8)
 	u[9] = byte(clock)
 
-	copy(u[10:], hardwareAddr)
+	copy(u[10:], node)
 
 	u[6] |= 0x10 // set version to 1 (time based uuid)
 	u[8] &= 0x3F // clear variant
@@ -198,6 +208,17 @@ func (u UUID) Node() []byte {
 	return u[10:]
 }
 
+// Clock extracts the clock sequence of this UUID. It will return zero if the
+// UUID is not a time based UUID (version 1).
+func (u UUID) Clock() uint32 {
+	if u.Version() != 1 {
+		return 0
+	}
+
+	// Clock sequence is the lower 14bits of u[8:10]
+	return uint32(u[8]&0x3F)<<8 | uint32(u[9])
+}
+
 // Timestamp extracts the timestamp information from a time based UUID
 // (version 1).
 func (u UUID) Timestamp() int64 {

+ 24 - 0
uuid_test.go

@@ -142,6 +142,30 @@ func TestUUIDFromTime(t *testing.T) {
 	}
 }
 
+func TestTimeUUIDWith(t *testing.T) {
+	utcTime := time.Date(1982, 5, 5, 12, 34, 56, 400, time.UTC)
+	ts := int64(utcTime.Unix()-timeBase)*10000000 + int64(utcTime.Nanosecond()/100)
+	clockSeq := uint32(0x3FFF)           // Max number of clock sequence.
+	node := [7]byte{0, 1, 2, 3, 4, 5, 6} // The last element should be ignored.
+	uuid := TimeUUIDWith(ts, clockSeq, node[:])
+
+	if got := uuid.Variant(); got != VariantIETF {
+		t.Errorf("wrong variant. expected %d got %d", VariantIETF, got)
+	}
+	if got, want := uuid.Version(), 1; got != want {
+		t.Errorf("wrong version. Expected %v got %v", want, got)
+	}
+	if got := uuid.Timestamp(); got != int64(ts) {
+		t.Errorf("wrong timestamp. Expected %v got %v", ts, got)
+	}
+	if got := uuid.Clock(); uint32(got) != clockSeq {
+		t.Errorf("wrong clock. expected %v got %v", clockSeq, got)
+	}
+	if got, want := uuid.Node(), node[:6]; !bytes.Equal(got, want) {
+		t.Errorf("wrong node. expected %x, bot %x", want, got)
+	}
+}
+
 func TestParseUUID(t *testing.T) {
 	uuid, _ := ParseUUID("486f3a88-775b-11e3-ae07-d231feb1dc81")
 	if uuid.Time() != time.Date(2014, 1, 7, 5, 19, 29, 222516000, time.UTC) {