@@ -44,15 +44,15 @@ func NewV7FromReader(r io.Reader) (UUID, error) {
4444
4545// makeV7 fill 48 bits time (uuid[0] - uuid[5]), set version b0111 (uuid[6])
4646// uuid[8] already has the right version number (Variant is 10)
47- // see function NewV7 and NewV7FromReader
47+ // see function NewV7 and NewV7FromReader
4848func makeV7 (uuid []byte ) {
4949 /*
5050 0 1 2 3
5151 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
5252 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
5353 | unix_ts_ms |
5454 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
55- | unix_ts_ms | ver | rand_a |
55+ | unix_ts_ms | ver | rand_a (12 bit seq) |
5656 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
5757 |var| rand_b |
5858 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
@@ -61,7 +61,7 @@ func makeV7(uuid []byte) {
6161 */
6262 _ = uuid [15 ] // bounds check
6363
64- t := timeNow (). UnixMilli ()
64+ t , s := getV7Time ()
6565
6666 uuid [0 ] = byte (t >> 40 )
6767 uuid [1 ] = byte (t >> 32 )
@@ -70,6 +70,35 @@ func makeV7(uuid []byte) {
7070 uuid [4 ] = byte (t >> 8 )
7171 uuid [5 ] = byte (t )
7272
73- uuid [6 ] = 0x70 | (uuid [6 ] & 0x0F )
74- // uuid[8] has already has right version
73+ uuid [6 ] = 0x70 | (0x0F & byte (s >> 8 ))
74+ uuid [7 ] = byte (s )
75+ }
76+
77+ // lastV7time is the last last time we returned stored as:
78+ //
79+ // 52 bits of time in milliseconds since epoch
80+ // 12 bits of (fractional nanoseconds) >> 8
81+ var lastV7time int64
82+
83+ const nanoPerMilli = 1000000
84+
85+ // getV7Time returns the time in milliseconds and nanoseconds / 256.
86+ // The returned (milli << 12 + seq) is guarenteed to be greater than
87+ // (milli << 12 + seq) returned by any previous call to getV7Time.
88+ func getV7Time () (milli , seq int64 ) {
89+ timeMu .Lock ()
90+ defer timeMu .Unlock ()
91+
92+ nano := timeNow ().UnixNano ()
93+ milli = nano / nanoPerMilli
94+ // Sequence number is between 0 and 3906 (nanoPerMilli>>8)
95+ seq = (nano - milli * nanoPerMilli ) >> 8
96+ now := milli << 12 + seq
97+ if now <= lastV7time {
98+ now = lastV7time + 1
99+ milli = now >> 12
100+ seq = now & 0xfff
101+ }
102+ lastV7time = now
103+ return milli , seq
75104}
0 commit comments