PluginProbe
Media Cloud Sync / 1.4.2
Media Cloud Sync v1.4.2
1.4.2 1.4.1 1.4.0 1.3.12 1.3.11 1.3.10 trunk 1.0.0 1.0.1 1.0.2 1.0.3 1.1.0 1.1.1 1.2.0 1.2.10 1.2.11 1.2.12 1.2.13 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 All 36 releases
media-cloud-sync / includes / sdk / google / ramsey / uuid / src / Converter / Time / PhpTimeConverter.php

PhpTimeConverter.php in Media Cloud Sync 1.4.2, at includes/sdk/google/ramsey/uuid/src/Converter/Time/PhpTimeConverter.php

132 lines 5.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * This file is part of the ramsey/uuid library
5 *
6 * For the full copyright and license information, please view the LICENSE
7 * file that was distributed with this source code.
8 *
9 * @copyright Copyright (c) Ben Ramsey <[email protected]>
10 * @license http://opensource.org/licenses/MIT MIT
11 */
12 declare (strict_types=1);
13 namespace Dudlewebs\WPMCS\GCP\Ramsey\Uuid\Converter\Time;
14
15 use Dudlewebs\WPMCS\GCP\Ramsey\Uuid\Converter\TimeConverterInterface;
16 use Dudlewebs\WPMCS\GCP\Ramsey\Uuid\Math\BrickMathCalculator;
17 use Dudlewebs\WPMCS\GCP\Ramsey\Uuid\Math\CalculatorInterface;
18 use Dudlewebs\WPMCS\GCP\Ramsey\Uuid\Type\Hexadecimal;
19 use Dudlewebs\WPMCS\GCP\Ramsey\Uuid\Type\Integer as IntegerObject;
20 use Dudlewebs\WPMCS\GCP\Ramsey\Uuid\Type\Time;
21 use function count;
22 use function dechex;
23 use function explode;
24 use function is_float;
25 use function is_int;
26 use function str_pad;
27 use function strlen;
28 use function substr;
29 use const STR_PAD_LEFT;
30 use const STR_PAD_RIGHT;
31 /**
32 * PhpTimeConverter uses built-in PHP functions and standard math operations available to the PHP programming language
33 * to provide facilities for converting parts of time into representations that may be used in UUIDs
34 *
35 * @immutable
36 */
37 class PhpTimeConverter implements TimeConverterInterface
38 {
39 /**
40 * The number of 100-nanosecond intervals from the Gregorian calendar epoch to the Unix epoch.
41 */
42 private const GREGORIAN_TO_UNIX_INTERVALS = 0x1b21dd213814000;
43 /**
44 * The number of 100-nanosecond intervals in one second.
45 */
46 private const SECOND_INTERVALS = 10000000;
47 /**
48 * The number of 100-nanosecond intervals in one microsecond.
49 */
50 private const MICROSECOND_INTERVALS = 10;
51 private int $phpPrecision;
52 private CalculatorInterface $calculator;
53 private TimeConverterInterface $fallbackConverter;
54 public function __construct(?CalculatorInterface $calculator = null, ?TimeConverterInterface $fallbackConverter = null)
55 {
56 if ($calculator === null) {
57 $calculator = new BrickMathCalculator();
58 }
59 if ($fallbackConverter === null) {
60 $fallbackConverter = new GenericTimeConverter($calculator);
61 }
62 $this->calculator = $calculator;
63 $this->fallbackConverter = $fallbackConverter;
64 $this->phpPrecision = (int) \ini_get('precision');
65 }
66 public function calculateTime(string $seconds, string $microseconds) : Hexadecimal
67 {
68 $seconds = new IntegerObject($seconds);
69 /** @phpstan-ignore possiblyImpure.new */
70 $microseconds = new IntegerObject($microseconds);
71 /** @phpstan-ignore possiblyImpure.new */
72 // Calculate the count of 100-nanosecond intervals since the Gregorian calendar epoch
73 // for the given seconds and microseconds.
74 $uuidTime = (int) $seconds->toString() * self::SECOND_INTERVALS + (int) $microseconds->toString() * self::MICROSECOND_INTERVALS + self::GREGORIAN_TO_UNIX_INTERVALS;
75 // Check to see whether we've overflowed the max/min integer size.
76 // If so, we will default to a different time converter.
77 // @phpstan-ignore function.alreadyNarrowedType (the integer value might have overflowed)
78 if (!is_int($uuidTime)) {
79 return $this->fallbackConverter->calculateTime($seconds->toString(), $microseconds->toString());
80 }
81 /** @phpstan-ignore possiblyImpure.new */
82 return new Hexadecimal(str_pad(dechex($uuidTime), 16, '0', STR_PAD_LEFT));
83 }
84 public function convertTime(Hexadecimal $uuidTimestamp) : Time
85 {
86 $timestamp = $this->calculator->toInteger($uuidTimestamp);
87 // Convert the 100-nanosecond intervals into seconds and microseconds.
88 $splitTime = $this->splitTime(($timestamp->toString() - self::GREGORIAN_TO_UNIX_INTERVALS) / self::SECOND_INTERVALS);
89 if (count($splitTime) === 0) {
90 return $this->fallbackConverter->convertTime($uuidTimestamp);
91 }
92 /** @phpstan-ignore possiblyImpure.new */
93 return new Time($splitTime['sec'], $splitTime['usec']);
94 }
95 /**
96 * @param float | int $time The time to split into seconds and microseconds
97 *
98 * @return string[]
99 *
100 * @pure
101 */
102 private function splitTime(float|int $time) : array
103 {
104 $split = explode('.', (string) $time, 2);
105 // If the $time value is a float but $split only has 1 element, then the float math was rounded up to the next
106 // second, so we want to return an empty array to allow use of the fallback converter.
107 if (is_float($time) && count($split) === 1) {
108 return [];
109 }
110 if (count($split) === 1) {
111 return ['sec' => $split[0], 'usec' => '0'];
112 }
113 // If the microseconds are less than six characters AND the length of the number is greater than or equal to the
114 // PHP precision, then it's possible that we lost some precision for the microseconds. Return an empty array so
115 // that we can choose to use the fallback converter.
116 if (strlen($split[1]) < 6 && strlen((string) $time) >= $this->phpPrecision) {
117 return [];
118 }
119 $microseconds = $split[1];
120 // Ensure the microseconds are no longer than 6 digits. If they are,
121 // truncate the number to the first 6 digits and round up, if needed.
122 if (strlen($microseconds) > 6) {
123 $roundingDigit = (int) substr($microseconds, 6, 1);
124 $microseconds = (int) substr($microseconds, 0, 6);
125 if ($roundingDigit >= 5) {
126 $microseconds++;
127 }
128 }
129 return ['sec' => $split[0], 'usec' => str_pad((string) $microseconds, 6, '0', STR_PAD_RIGHT)];
130 }
131 }
132