Rev 85 | Rev 87 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 85 | Rev 86 | ||
---|---|---|---|
Line 840... | Line 840... | ||
840 | if (strtolower($signature) == '5ce32bd83b96') { |
840 | if (strtolower($signature) == '5ce32bd83b96') { |
841 | // HickelSOFT "SQL Server sortable UUID in C#" |
841 | // HickelSOFT "SQL Server sortable UUID in C#" |
842 | // Version 2: Resolution of 1 milliseconds, random part of 18 bits, UTC time, UUIDv8 conform. |
842 | // Version 2: Resolution of 1 milliseconds, random part of 18 bits, UTC time, UUIDv8 conform. |
843 | // Example: 2088dc33-000d-8045-87e8-5ce32bd83b96 |
843 | // Example: 2088dc33-000d-8045-87e8-5ce32bd83b96 |
844 | // Block 4 |
844 | // Block 4 |
845 | $rnd2bits = hexdec(substr($uuid,16,1)) & 0x3; |
845 | $unused2bits = hexdec(substr($uuid,16,1)) & 0x3; |
846 | $year = hexdec(substr($uuid,17,3)); |
846 | $year = hexdec(substr($uuid,17,3)); |
847 | // Block 3 |
847 | // Block 3 |
848 | $dayOfYear = hexdec(substr($uuid,13,3)); // 1..366 |
848 | $dayOfYear = hexdec(substr($uuid,13,3)); // 1..366 |
849 | $day = (($dayOfYear < 1) || ($dayOfYear > 366)) ? "XX" : intval(getDateFromDay($year, $dayOfYear)->format('d')); |
849 | $day = (($dayOfYear < 1) || ($dayOfYear > 366)) ? "XX" : intval(getDateFromDay($year, $dayOfYear)->format('d')); |
850 | $month = (($dayOfYear < 1) || ($dayOfYear > 366)) ? "XX" : intval(getDateFromDay($year, $dayOfYear)->format('m')); |
850 | $month = (($dayOfYear < 1) || ($dayOfYear > 366)) ? "XX" : intval(getDateFromDay($year, $dayOfYear)->format('m')); |
Line 872... | Line 872... | ||
872 | echo sprintf("%-32s %s\n", "Random 16 bits:", "[0x$rnd16bits] 0b".str_pad("".base_convert($rnd16bits, 16, 2), 16, '0', STR_PAD_LEFT)); |
872 | echo sprintf("%-32s %s\n", "Random 16 bits:", "[0x$rnd16bits] 0b".str_pad("".base_convert($rnd16bits, 16, 2), 16, '0', STR_PAD_LEFT)); |
873 | echo sprintf("%-32s %s\n", "Milliseconds:", "[0x".substr($uuid,4,2)."] $milliseconds $deviation"); |
873 | echo sprintf("%-32s %s\n", "Milliseconds:", "[0x".substr($uuid,4,2)."] $milliseconds $deviation"); |
874 | echo sprintf("%-32s %s\n", "Seconds:", "[0x".substr($uuid,6,2)."] $seconds"); |
874 | echo sprintf("%-32s %s\n", "Seconds:", "[0x".substr($uuid,6,2)."] $seconds"); |
875 | echo sprintf("%-32s %s\n", "Minute of day:", "[0x".substr($uuid,8,4)."] $minuteOfDay (".str_pad("$hours",2,'0',STR_PAD_LEFT).":".str_pad("$minutes",2,'0',STR_PAD_LEFT).")"); |
875 | echo sprintf("%-32s %s\n", "Minute of day:", "[0x".substr($uuid,8,4)."] $minuteOfDay (".str_pad("$hours",2,'0',STR_PAD_LEFT).":".str_pad("$minutes",2,'0',STR_PAD_LEFT).")"); |
876 | echo sprintf("%-32s %s\n", "Day of year:", "[0x".substr($uuid,13,3)."] $dayOfYear (Day=$day, Month=$month)"); |
876 | echo sprintf("%-32s %s\n", "Day of year:", "[0x".substr($uuid,13,3)."] $dayOfYear (Day=$day, Month=$month)"); |
877 | echo sprintf("%-32s %s\n", "Random 2 bits:", "[$rnd2bits] 0b".str_pad("".base_convert("$rnd2bits", 16, 2), 2, '0', STR_PAD_LEFT)); |
877 | echo sprintf("%-32s %s\n", "Unused 2 bits:", "[$unused2bits] 0b".str_pad("".base_convert("$unused2bits", 16, 2), 2, '0', STR_PAD_LEFT)); |
878 | echo sprintf("%-32s %s\n", "Year:", "[0x".substr($uuid,17,3)."] $year"); |
878 | echo sprintf("%-32s %s\n", "Year:", "[0x".substr($uuid,17,3)."] $year"); |
879 | echo sprintf("%-32s %s\n", "Signature:", "[0x".substr($uuid,20,12)."] HickelSOFT \"SQL Server Sortable Custom UUID\", Version 2 (very likely)"); |
879 | echo sprintf("%-32s %s\n", "Signature:", "[0x".substr($uuid,20,12)."] HickelSOFT \"SQL Server Sortable Custom UUID\", Version 2 (very likely)"); |
880 | echo sprintf("%-32s %s\n", "UTC Date Time:", "$utc_time $deviation"); |
880 | echo sprintf("%-32s %s\n", "UTC Date Time:", "$utc_time $deviation"); |
881 | } |
881 | } |
882 | } else if (strtolower($signature) == '000000000000') { |
882 | } else if (strtolower($signature) == '000000000000') { |
Line 1551... | Line 1551... | ||
1551 | } |
1551 | } |
1552 | 1552 | ||
1553 | /** |
1553 | /** |
1554 | * The sorting of SQL Server is rather confusing and incompatible with UUIDv6 and UUIDv7. |
1554 | * The sorting of SQL Server is rather confusing and incompatible with UUIDv6 and UUIDv7. |
1555 | * Therefore this method generates UUID which are sortable by SQL Server. |
1555 | * Therefore this method generates UUID which are sortable by SQL Server. |
1556 | * Version 1: Resolution of 1 milliseconds, random part of 16 bits, local timezone, NOT UUIDv8 conform. |
1556 | * Version 1: Resolution of 1 milliseconds, random part of 16 bits, local timezone, 48 zero bits "signature", NOT UUIDv8 conform. |
1557 | * Version 2: Resolution of 1 milliseconds, random part of 18 bits, UTC time, UUIDv8 conform. |
1557 | * Version 2: Resolution of 1 milliseconds, random part of 16 bits, UTC time, 48 bit random "signature", UUIDv8 conform. |
1558 | * C# implementation: https://gist.github.com/danielmarschall/7fafd270a3bc107d38e8449ce7420c25 |
1558 | * C# implementation: https://gist.github.com/danielmarschall/7fafd270a3bc107d38e8449ce7420c25 |
1559 | * PHP implementation: https://github.com/danielmarschall/uuid_mac_utils/blob/master/includes/uuid_utils.inc.php |
1559 | * PHP implementation: https://github.com/danielmarschall/uuid_mac_utils/blob/master/includes/uuid_utils.inc.php |
1560 | * |
1560 | * |
1561 | * @param int $hickelUuidVersion (optional) |
1561 | * @param int $hickelUuidVersion (optional) |
1562 | * @param DateTime $dt (optional) |
1562 | * @param DateTime $dt (optional) |
Line 1580... | Line 1580... | ||
1580 | if ($hickelUuidVersion == 1) { |
1580 | if ($hickelUuidVersion == 1) { |
1581 | $year = $dt->format('Y'); |
1581 | $year = $dt->format('Y'); |
1582 | $block4 = substr($year, 2, 2).substr($year, 0, 2); // Example: 0x2420 = 2024 |
1582 | $block4 = substr($year, 2, 2).substr($year, 0, 2); // Example: 0x2420 = 2024 |
1583 | } else { |
1583 | } else { |
1584 | $variant = 0x8; // First nibble needs to be 0b10_ (0x8-0xB) for "RFC 4122bis". We use it to store 2 more random bits. |
1584 | $variant = 0x8; // First nibble needs to be 0b10_ (0x8-0xB) for "RFC 4122bis". We use it to store 2 more random bits. |
1585 | $rnd2bits = _random_int(0x0, 0x3); |
1585 | $unused2bits = 0; // Cannot be used for random, because it would affect the sorting |
1586 | $year = $dt->format('Y'); |
1586 | $year = $dt->format('Y'); |
1587 | $block4 = sprintf('%01x%03x', $variant + ($rnd2bits & 0x3), $year); |
1587 | $block4 = sprintf('%01x%03x', $variant + ($unused2bits & 0x3), $year); |
1588 | } |
1588 | } |
1589 | 1589 | ||
1590 | // Then: Sort block 3, bytes from right to left (i.e. 0100 < 1000 < 0001 < 0010) |
1590 | // Then: Sort block 3, bytes from right to left (i.e. 0100 < 1000 < 0001 < 0010) |
1591 | if ($hickelUuidVersion == 1) { |
1591 | if ($hickelUuidVersion == 1) { |
1592 | $block3 = $dt->format('dm'); |
1592 | $block3 = $dt->format('dm'); |
Line 1613... | Line 1613... | ||
1613 | $millisecond8bits = round(($dt->format('v') / 999) * 255); // deviation -2ms..2ms |
1613 | $millisecond8bits = round(($dt->format('v') / 999) * 255); // deviation -2ms..2ms |
1614 | $rnd16bits = _random_int(0x0000, 0xFFFF); |
1614 | $rnd16bits = _random_int(0x0000, 0xFFFF); |
1615 | $block1 = sprintf('%04x%02x%02x', $rnd16bits, $millisecond8bits, $dt->format('s')); |
1615 | $block1 = sprintf('%04x%02x%02x', $rnd16bits, $millisecond8bits, $dt->format('s')); |
1616 | } |
1616 | } |
1617 | 1617 | ||
1618 | // Now build and parse UUID |
- | |
1619 | usleep((int)ceil(999 / 255)); // Make sure that "millisecond" is not repeated on this system |
1618 | $sleep_ms = (int)ceil(999 / 255); // Make sure that "millisecond" is not repeated on this system |
- | 1619 | if (time_nanosleep(0,$sleep_ms*1000*1000) !== true) usleep($sleep_ms*1000); |
|
- | 1620 | ||
1620 | return strtolower("$block1-$block2-$block3-$block4-$block5"); |
1621 | return strtolower("$block1-$block2-$block3-$block4-$block5"); |
1621 | } |
1622 | } |
1622 | 1623 | ||
1623 | # -------------------------------------- |
1624 | # -------------------------------------- |
1624 | 1625 |