Rev 81 | Rev 83 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 81 | Rev 82 | ||
---|---|---|---|
Line 1546... | Line 1546... | ||
1546 | substr($hash, 12, 4).'-'. |
1546 | substr($hash, 12, 4).'-'. |
1547 | substr($hash, 16, 4).'-'. |
1547 | substr($hash, 16, 4).'-'. |
1548 | substr($hash, 20, 12); |
1548 | substr($hash, 20, 12); |
1549 | } |
1549 | } |
1550 | 1550 | ||
- | 1551 | /** |
|
- | 1552 | * The sorting of SQL Server is rather confusing and incompatible with UUIDv6 and UUIDv7. |
|
- | 1553 | * Therefore this method generates UUID which are sortable by SQL Server. |
|
- | 1554 | * Version 1: Resolution of 1 milliseconds, random part of 16 bits, local timezone, NOT UUIDv8 conform. |
|
- | 1555 | * Version 2: Resolution of 1 milliseconds, random part of 18 bits, UTC time, UUIDv8 conform. |
|
- | 1556 | * C# implementation: https://gist.github.com/danielmarschall/7fafd270a3bc107d38e8449ce7420c25 |
|
- | 1557 | * PHP implementation: https://github.com/danielmarschall/uuid_mac_utils/blob/master/includes/uuid_utils.inc.php |
|
- | 1558 | * |
|
- | 1559 | * @param int $hickelUuidVersion (optional) |
|
- | 1560 | * @param DateTime $dt (optional) |
|
- | 1561 | * @return string The UUID |
|
- | 1562 | */ |
|
- | 1563 | function gen_uuid_v8_sqlserver_sortable(int $hickelUuidVersion = 2, DateTime $dt = null): string { |
|
- | 1564 | // The sorting in SQL Server is like this: |
|
- | 1565 | ||
- | 1566 | if ($dt == null) $dt = new DateTime(); |
|
- | 1567 | ||
- | 1568 | // First Sort block 5, nibbles from left to right (i.e. 000000000001 < 000000000010 < ... < 010000000000 < 100000000000) |
|
- | 1569 | if ($hickelUuidVersion == 1) { |
|
- | 1570 | $block5 = "000000000000"; |
|
- | 1571 | } else if ($hickelUuidVersion == 2) { |
|
- | 1572 | $block5 = "4849434B454C"/*Hex:"HICKEL"*/; |
|
- | 1573 | } else { |
|
- | 1574 | throw new Exception("Invalid version"); |
|
- | 1575 | } |
|
- | 1576 | ||
- | 1577 | // Then: Sort block 4, nibbles from left to right |
|
- | 1578 | if ($hickelUuidVersion == 1) { |
|
- | 1579 | $year = $dt->format('Y'); |
|
- | 1580 | $block4 = substr($year, 2, 2).substr($year, 0, 2); // Example: 0x2420 = 2024 |
|
- | 1581 | } else { |
|
- | 1582 | $variant = 0x8; // First nibble needs to be 0b10_ (0x8-0xB) for "RFC 4122bis". We use it to store 2 more random bits. |
|
- | 1583 | $rnd2bits = rand(0x0, 0x3); |
|
- | 1584 | $year = $dt->format('Y'); |
|
- | 1585 | $block4 = sprintf('%01x%03x', $variant + ($rnd2bits & 0x3), $year); |
|
- | 1586 | } |
|
- | 1587 | ||
- | 1588 | // Then: Sort block 3, bytes from right to left (i.e. 0100 < 1000 < 0001 < 0010) |
|
- | 1589 | if ($hickelUuidVersion == 1) { |
|
- | 1590 | $block3 = $dt->format('dm'); |
|
- | 1591 | } else { |
|
- | 1592 | $uuidVersion = 8; // First nibble needs to be "8" for "UUIDv8 = Custom UUID" |
|
- | 1593 | $dayOfYear = intval($dt->format('z')) + 1; /* 1..366 */ |
|
- | 1594 | $block3 = sprintf('%01x%03x', $uuidVersion, $dayOfYear); |
|
- | 1595 | } |
|
- | 1596 | ||
- | 1597 | // Then: Sort block 2, bytes from right to left |
|
- | 1598 | if ($hickelUuidVersion == 1) { |
|
- | 1599 | $block2 = $dt->format('ih'); |
|
- | 1600 | } else { |
|
- | 1601 | $minuteOfDay = (intval($dt->format('i')) + intval($dt->format('h')) * 60) + 1; // 1..1440 |
|
- | 1602 | $block2 = sprintf('%04x', $minuteOfDay); |
|
- | 1603 | } |
|
- | 1604 | ||
- | 1605 | // Then: Sort block 1, bytes from right to left |
|
- | 1606 | $millisecond8bits = ceil(($dt->format('v') / 999) * 255); |
|
- | 1607 | if ($hickelUuidVersion == 1) { |
|
- | 1608 | $rnd16bits = rand(0x0000, 0xFFFF-1); |
|
- | 1609 | $block1 = sprintf('%04x%02x', $rnd16bits, $millisecond8bits).$dt->format('s'); |
|
- | 1610 | } else { |
|
- | 1611 | $rnd16bits = rand(0x0000, 0xFFFF); |
|
- | 1612 | $block1 = sprintf('%04x%02x%02x', $rnd16bits, $millisecond8bits, $dt->format('s')); |
|
- | 1613 | } |
|
- | 1614 | ||
- | 1615 | // Now build and parse UUID |
|
- | 1616 | usleep((int)ceil(999 / 255)); // Make sure that "millisecond" is not repeated on this system |
|
- | 1617 | return "$block1-$block2-$block3-$block4-$block5"; |
|
- | 1618 | } |
|
- | 1619 | ||
1551 | # -------------------------------------- |
1620 | # -------------------------------------- |
1552 | 1621 | ||
1553 | // http://php.net/manual/de/function.hex2bin.php#113057 |
1622 | // http://php.net/manual/de/function.hex2bin.php#113057 |
1554 | if (!function_exists('hex2bin')) { |
1623 | if (!function_exists('hex2bin')) { |
1555 | function hex2bin($str) { |
1624 | function hex2bin($str) { |