8000 [Uid] Ensure ULIDs are monotonic even when the time goes backward · symfony/symfony@83c4681 · GitHub
[go: up one dir, main page]

Skip to content

Commit 83c4681

Browse files
[Uid] Ensure ULIDs are monotonic even when the time goes backward
1 parent 1f4cfc7 commit 83c4681

File tree

2 files changed

+10
-4
lines changed

2 files changed

+10
-4
lines changed

src/Symfony/Component/Uid/Tests/UlidTest.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,16 @@ public function testGenerate()
2626
{
2727
$a = new Ulid();
2828
$b = new Ulid();
29+
usleep(-10000);
30+
$c = new Ulid();
2931

3032
$this->assertSame(0, strncmp($a, $b, 20));
33+
$this->assertSame(0, strncmp($a, $c, 20));
3134
$a = base_convert(strtr(substr($a, -6), 'ABCDEFGHJKMNPQRSTVWXYZ', 'abcdefghijklmnopqrstuv'), 32, 10);
3235
$b = base_convert(strtr(substr($b, -6), 'ABCDEFGHJKMNPQRSTVWXYZ', 'abcdefghijklmnopqrstuv'), 32, 10);
36+
$c = base_convert(strtr(substr($c, -6), 'ABCDEFGHJKMNPQRSTVWXYZ', 'abcdefghijklmnopqrstuv'), 32, 10);
3337
$this->assertSame(1, $b - $a);
38+
$this->assertSame(1, $c - $b);
3439
}
3540

3641
public function testWithInvalidUlid()

src/Symfony/Component/Uid/Ulid.php

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -137,10 +137,10 @@ public function getDateTime(): \DateTimeImmutable
137137
}
138138

139139
if (4 > \strlen($time)) {
140-
$time = str_pad($time, 4, '0', \STR_PAD_LEFT);
140+
$time = '000'.$time;
141141
}
142142

143-
return \DateTimeImmutable::createFromFormat('U.u', substr_replace($time, '.', -3, 0));
143+
return \DateTimeImmutable::createFromFormat('U.v', substr_replace($time, '.', -3, 0));
144144
}
145145

146146
public static function generate(\DateTimeInterface $time = null): string
@@ -149,7 +149,7 @@ public static function generate(\DateTimeInterface $time = null): string
149149
return self::doGenerate();
150150
}
151151

152-
if (0 > $time = substr($time->format('Uu'), 0, -3)) {
152+
if (0 > $time = $time->format('Uv')) {
153153
throw new \InvalidArgumentException('The timestamp must be positive.');
154154
}
155155

@@ -163,7 +163,7 @@ private static function doGenerate(string $mtime = null): string
163163
$time = substr($time, 11).substr($time, 2, 3);
164164
}
165165

166-
if ($time !== self::$time) {
166+
if ($time > self::$time || (null !== $mtime && $time !== self::$time)) {
167167
$r = unpack('nr1/nr2/nr3/nr4/nr', random_bytes(10));
168168
$r['r1'] |= ($r['r'] <<= 4) & 0xF0000;
169169
$r['r2'] |= ($r['r'] <<= 4) & 0xF0000;
@@ -186,6 +186,7 @@ private static function doGenerate(string $mtime = null): string
186186
}
187187

188188
++self::$rand[$i];
189+
$time = self::$time;
189190
}
190191

191192
if (\PHP_INT_SIZE >= 8) {

0 commit comments

Comments
 (0)
0