minor #36053 [Uid] make Uuid::getTime() return subseconds info (nicolas-grekas)
This PR was merged into the 5.1-dev branch.
Discussion
----------
[Uid] make Uuid::getTime() return subseconds info
| Q | A
| ------------- | ---
| Branch? | master
| Bug fix? | no
| New feature? | no
| Deprecations? | no
| Tickets | -
| License | MIT
| Doc PR | -
A UUID timestamp contains 60bit of data, but a timestamp barely contains 31bit.
Let's return a float instead.
Commits
-------
5a170b80ed
[Uid] make Uuid::getTime() return subseconds info
This commit is contained in:
commit
08bb79b174
85
src/Symfony/Component/Uid/InternalUtil.php
Normal file
85
src/Symfony/Component/Uid/InternalUtil.php
Normal file
@ -0,0 +1,85 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Uid;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
*/
|
||||
class InternalUtil
|
||||
{
|
||||
public static function toBinary(string $digits): string
|
||||
{
|
||||
$bytes = '';
|
||||
$len = \strlen($digits);
|
||||
|
||||
while ($len > $i = strspn($digits, '0')) {
|
||||
for ($j = 2, $r = 0; $i < $len; $i += $j, $j = 0) {
|
||||
do {
|
||||
$r *= 10;
|
||||
$d = (int) substr($digits, $i, ++$j);
|
||||
} while ($i + $j < $len && $r + $d < 256);
|
||||
|
||||
$j = \strlen((string) $d);
|
||||
$q = str_pad(($d += $r) >> 8, $j, '0', STR_PAD_LEFT);
|
||||
$digits = substr_replace($digits, $q, $i, $j);
|
||||
$r = $d % 256;
|
||||
}
|
||||
|
||||
$bytes .= \chr($r);
|
||||
}
|
||||
|
||||
return strrev($bytes);
|
||||
}
|
||||
|
||||
public static function toDecimal(string $bytes): string
|
||||
{
|
||||
$digits = '';
|
||||
$len = \strlen($bytes);
|
||||
|
||||
while ($len > $i = strspn($bytes, "\0")) {
|
||||
for ($r = 0; $i < $len; $i += $j) {
|
||||
$j = $d = 0;
|
||||
do {
|
||||
$r <<= 8;
|
||||
$d = ($d << 8) + \ord($bytes[$i + $j]);
|
||||
} while ($i + ++$j < $len && $r + $d < 10);
|
||||
|
||||
if (256 < $d) {
|
||||
$q = intdiv($d += $r, 10);
|
||||
$bytes[$i] = \chr($q >> 8);
|
||||
$bytes[1 + $i] = \chr($q & 0xFF);
|
||||
} else {
|
||||
$bytes[$i] = \chr(intdiv($d += $r, 10));
|
||||
}
|
||||
$r = $d % 10;
|
||||
}
|
||||
|
||||
$digits .= (string) $r;
|
||||
}
|
||||
|
||||
return strrev($digits);
|
||||
}
|
||||
|
||||
public static function binaryAdd(string $a, string $b): string
|
||||
{
|
||||
$sum = 0;
|
||||
for ($i = 7; 0 <= $i; --$i) {
|
||||
$sum += \ord($a[$i]) + \ord($b[$i]);
|
||||
$a[$i] = \chr($sum & 0xFF);
|
||||
$sum >>= 8;
|
||||
}
|
||||
|
||||
return $a;
|
||||
}
|
||||
}
|
@ -117,7 +117,7 @@ class UuidTest extends TestCase
|
||||
$uuid = new Uuid(self::A_UUID_V1);
|
||||
|
||||
$this->assertSame(Uuid::VARIANT_DCE, $uuid->getVariant());
|
||||
$this->assertSame(1583245966, $uuid->getTime());
|
||||
$this->assertSame(1583245966.746458, $uuid->getTime());
|
||||
$this->assertSame('3499710062d0', $uuid->getMac());
|
||||
$this->assertSame(self::A_UUID_V1, (string) $uuid);
|
||||
}
|
||||
|
@ -28,6 +28,12 @@ class Uuid implements \JsonSerializable
|
||||
public const VARIANT_MICROSOFT = UUID_VARIANT_MICROSOFT;
|
||||
public const VARIANT_OTHER = UUID_VARIANT_OTHER;
|
||||
|
||||
// https://tools.ietf.org/html/rfc4122#section-4.1.4
|
||||
// 0x01b21dd213814000 is the number of 100-ns intervals between the
|
||||
// UUID epoch 1582-10-15 00:00:00 and the Unix epoch 1970-01-01 00:00:00.
|
||||
private const TIME_OFFSET_INT = 0x01b21dd213814000;
|
||||
private const TIME_OFFSET_COM = "\xfe\x4d\xe2\x2d\xec\x7e\xc0\x00";
|
||||
|
||||
private $uuid;
|
||||
|
||||
public function __construct(string $uuid = null)
|
||||
@ -105,13 +111,23 @@ class Uuid implements \JsonSerializable
|
||||
return uuid_variant($this->uuid);
|
||||
}
|
||||
|
||||
public function getTime(): int
|
||||
public function getTime(): float
|
||||
{
|
||||
if (self::TYPE_1 !== $t = uuid_type($this->uuid)) {
|
||||
throw new \LogicException("UUID of type $t doesn't contain a time.");
|
||||
}
|
||||
|
||||
return uuid_time($this->uuid);
|
||||
$time = '0'.substr($this->uuid, 15, 3).substr($this->uuid, 9, 4).substr($this->uuid, 0, 8);
|
||||
|
||||
if (\PHP_INT_SIZE >= 8) {
|
||||
return (hexdec($time) - self::TIME_OFFSET_INT) / 10000000;
|
||||
}
|
||||
|
||||
$time = str_pad(hex2bin($time), 8, "\0", STR_PAD_LEFT);
|
||||
$time = InternalUtil::binaryAdd($time, self::TIME_OFFSET_COM);
|
||||
$time[0] = $time[0] & "\x7F";
|
||||
|
||||
return InternalUtil::toDecimal($time) / 10000000;
|
||||
}
|
||||
|
||||
public function getMac(): string
|
||||
|
Reference in New Issue
Block a user