@@ -60,6 +60,32 @@ class UUID
6060 /** @internal */
6161 private const REPLACE_ARR = array ('urn: ' , 'uuid: ' , '- ' , '{ ' , '} ' );
6262
63+ /** @internal */
64+ private static $ unixts = 0 ;
65+
66+ /** @internal */
67+ private static $ subsec = 0 ;
68+
69+ private static function getUnixTime ()
70+ {
71+ $ timestamp = microtime (false );
72+ $ unixts = intval (substr ($ timestamp , 11 ), 10 );
73+ $ subsec = intval (substr ($ timestamp , 2 , 7 ), 10 );
74+ if (self ::$ unixts > $ unixts || self ::$ unixts === $ unixts && self ::$ subsec >= $ subsec ) {
75+ $ unixts = self ::$ unixts ;
76+ $ subsec = self ::$ subsec ;
77+ if ($ subsec === 9999999 ) {
78+ $ subsec = 0 ;
79+ $ unixts ++;
80+ } else {
81+ $ subsec ++;
82+ }
83+ }
84+ self ::$ unixts = $ unixts ;
85+ self ::$ subsec = $ subsec ;
86+ return [$ unixts , $ subsec ];
87+ }
88+
6389 /** @internal */
6490 private static function stripExtras ($ uuid )
6591 {
@@ -86,23 +112,23 @@ private static function getBytes($uuid)
86112 }
87113
88114 /** @internal */
89- private static function uuidFromHash ( $ hash , $ version )
115+ private static function uuidFromHex ( $ uhex , $ version )
90116 {
91117 return sprintf (
92118 '%08s-%04s-%04x-%04x-%12s ' ,
93119 // 32 bits for "time_low"
94- substr ($ hash , 0 , 8 ),
120+ substr ($ uhex , 0 , 8 ),
95121 // 16 bits for "time_mid"
96- substr ($ hash , 8 , 4 ),
122+ substr ($ uhex , 8 , 4 ),
97123 // 16 bits for "time_hi_and_version",
98124 // four most significant bits holds version number
99- (hexdec (substr ($ hash , 12 , 4 )) & 0x0fff ) | $ version << 12 ,
125+ (hexdec (substr ($ uhex , 12 , 4 )) & 0x0fff ) | $ version << 12 ,
100126 // 16 bits, 8 bits for "clk_seq_hi_res",
101127 // 8 bits for "clk_seq_low",
102128 // two most significant bits holds zero and one for variant DCE1.1
103- (hexdec (substr ($ hash , 16 , 4 )) & 0x3fff ) | 0x8000 ,
129+ (hexdec (substr ($ uhex , 16 , 4 )) & 0x3fff ) | 0x8000 ,
104130 // 48 bits for "node"
105- substr ($ hash , 20 , 12 )
131+ substr ($ uhex , 20 , 12 )
106132 );
107133 }
108134
@@ -119,9 +145,9 @@ public static function uuid3($namespace, $name)
119145 $ nbytes = self ::getBytes ($ namespace );
120146
121147 // Calculate hash value
122- $ hash = md5 ($ nbytes . $ name );
148+ $ uhex = md5 ($ nbytes . $ name );
123149
124- return self ::uuidFromHash ( $ hash , 3 );
150+ return self ::uuidFromHex ( $ uhex , 3 );
125151 }
126152
127153 /**
@@ -132,8 +158,8 @@ public static function uuid3($namespace, $name)
132158 public static function uuid4 ()
133159 {
134160 $ bytes = random_bytes (16 );
135- $ hash = bin2hex ($ bytes );
136- return self ::uuidFromHash ( $ hash , 4 );
161+ $ uhex = bin2hex ($ bytes );
162+ return self ::uuidFromHex ( $ uhex , 4 );
137163 }
138164
139165 /**
@@ -149,9 +175,9 @@ public static function uuid5($namespace, $name)
149175 $ nbytes = self ::getBytes ($ namespace );
150176
151177 // Calculate hash value
152- $ hash = sha1 ($ nbytes . $ name );
178+ $ uhex = sha1 ($ nbytes . $ name );
153179
154- return self ::uuidFromHash ( $ hash , 5 );
180+ return self ::uuidFromHex ( $ uhex , 5 );
155181 }
156182
157183 /**
@@ -163,17 +189,17 @@ public static function uuid5($namespace, $name)
163189 */
164190 public static function uuid6 ()
165191 {
166- $ time = microtime ( false );
167- $ time = substr ( $ time , 11 ) . substr ( $ time , 2 , 7 ) ;
192+ [ $ unixts , $ subsec ] = self :: getUnixTime ( );
193+ $ time = $ unixts * 10 ** 7 + $ subsec ;
168194 $ time = str_pad (dechex ($ time + self ::TIME_OFFSET_INT ), 16 , '0 ' , \STR_PAD_LEFT );
169195 $ time = sprintf (
170196 '%012s6%03s ' ,
171197 substr ($ time , -15 , 12 ),
172198 substr ($ time , -3 )
173199 );
174200 $ bytes = random_bytes (8 );
175- $ hash = $ time . bin2hex ($ bytes );
176- return self ::uuidFromHash ( $ hash , 6 );
201+ $ uhex = $ time . bin2hex ($ bytes );
202+ return self ::uuidFromHex ( $ uhex , 6 );
177203 }
178204
179205 /**
@@ -184,20 +210,18 @@ public static function uuid6()
184210 */
185211 public static function uuid7 ()
186212 {
187- $ time = microtime (false );
188- $ unixts = substr ($ time , 11 );
189- $ subsec = substr ($ time , 2 , 7 );
190- $ unixts = str_pad (dechex (intval ($ unixts , 10 )), 9 , '0 ' , \STR_PAD_LEFT );
191- $ subsec = str_pad (dechex (intval ($ subsec , 10 )), 6 , '0 ' , \STR_PAD_LEFT );
213+ [$ unixts , $ subsec ] = self ::getUnixTime ();
214+ $ unixts = str_pad (dechex ($ unixts ), 9 , '0 ' , \STR_PAD_LEFT );
215+ $ subsec = str_pad (dechex ($ subsec ), 6 , '0 ' , \STR_PAD_LEFT );
192216 $ time = sprintf (
193217 '%09s%03s7%03s ' ,
194218 $ unixts ,
195219 substr ($ subsec , 0 , 3 ),
196220 substr ($ subsec , -3 )
197221 );
198222 $ bytes = random_bytes (8 );
199- $ hash = $ time . bin2hex ($ bytes );
200- return self ::uuidFromHash ( $ hash , 7 );
223+ $ uhex = $ time . bin2hex ($ bytes );
224+ return self ::uuidFromHex ( $ uhex , 7 );
201225 }
202226
203227 /**
0 commit comments