Subversion Repositories uuid_mac_utils

Rev

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