1
|
|
|
<?php |
2
|
|
|
namespace Fwolf\Util\Uuid; |
3
|
|
|
|
4
|
|
|
/** |
5
|
|
|
* UUID generator using base-62 character, short version |
6
|
|
|
* |
7
|
|
|
* |
8
|
|
|
* second: 5 chars |
9
|
|
|
* microsecond: 4 chars, waste some number range (by * 1000000): |
10
|
|
|
* base_convert(999,999, 10, 62) = 4c91 |
11
|
|
|
* |
12
|
|
|
* So, For wider time range, we can start count timestamp from not |
13
|
|
|
* year 1970. And combine second and microsecond part together before |
14
|
|
|
* convert to base62. Result usable year raise to about 420 years. Detail: |
15
|
|
|
* |
16
|
|
|
* If offset time is 2009-10-10 = 1255104000 |
17
|
|
|
* Lifetime start: (base62 of 10{5 + 4 - 1}) / 10^6 + offset timestamp = |
18
|
|
|
* 1473444105 = 2016-09-10 02:01:45 |
19
|
|
|
* Lifetime end: base62 of Z{5 + 4} / 10^6 + offset timestamp = |
20
|
|
|
* 14792190546 = 2438-09-30 05:49:06 |
21
|
|
|
* |
22
|
|
|
* Why 2009-10-10? |
23
|
|
|
* Base62 10{5 + 4 - 1} / base10 10^6 = 218340105 = 1976-12-02 10:01:45 |
24
|
|
|
* Means it need to be 6-12-02 10:01:45 from start timestamp |
25
|
|
|
* Now(2016-10-10) - 6-12-02 10:01:45 = about 2009-10-10 |
26
|
|
|
* |
27
|
|
|
* |
28
|
|
|
* random: 5 chars |
29
|
|
|
* 62^5 = 916132831, about 1/5 of 16^8 = 4294967296, |
30
|
|
|
* but microsecond is 100x of general UUID. |
31
|
|
|
* |
32
|
|
|
* |
33
|
|
|
* @copyright Copyright 2016 Fwolf |
34
|
|
|
* @license http://opensource.org/licenses/MIT MIT |
35
|
|
|
*/ |
36
|
|
|
class Base62Short extends Base62 |
37
|
|
|
{ |
38
|
|
|
/** |
39
|
|
|
* {@inheritdoc} |
40
|
|
|
*/ |
41
|
|
|
const LENGTH = 15; |
42
|
|
|
|
43
|
|
|
/** |
44
|
|
|
* {@inheritdoc} |
45
|
|
|
*/ |
46
|
|
|
const LENGTH_SECOND = 5; |
47
|
|
|
|
48
|
|
|
/** |
49
|
|
|
* {@inheritdoc} |
50
|
|
|
*/ |
51
|
|
|
const LENGTH_MICROSECOND = 4; |
52
|
|
|
|
53
|
|
|
/** |
54
|
|
|
* {@inheritdoc} |
55
|
|
|
*/ |
56
|
|
|
const LENGTH_GROUP = 1; |
57
|
|
|
|
58
|
|
|
/** |
59
|
|
|
* {@inheritdoc} |
60
|
|
|
*/ |
61
|
|
|
const LENGTH_CUSTOM = 0; |
62
|
|
|
|
63
|
|
|
/** |
64
|
|
|
* {@inheritdoc} |
65
|
|
|
*/ |
66
|
|
|
const LENGTH_RANDOM = 5; |
67
|
|
|
|
68
|
|
|
/** |
69
|
|
|
* {@inheritdoc} |
70
|
|
|
*/ |
71
|
|
|
const LENGTH_CHECK_DIGIT = 0; |
72
|
|
|
|
73
|
|
|
/** |
74
|
|
|
* {@inheritdoc} |
75
|
|
|
*/ |
76
|
|
|
const SEPARATOR = ''; |
77
|
|
|
|
78
|
|
|
/** |
79
|
|
|
* Start offset of timestamp |
80
|
|
|
*/ |
81
|
|
|
const TIMESTAMP_OFFSET = 1255104000; // 2009-10-10 |
|
|
|
|
82
|
|
|
|
83
|
|
|
|
84
|
|
|
/** |
85
|
|
|
* {@inheritdoc} |
86
|
|
|
*/ |
87
|
|
|
public function explain($uuid) |
88
|
|
|
{ |
89
|
|
|
$explanation = parent::explain($uuid); |
90
|
|
|
|
91
|
|
|
$converter = $this->getBaseConverter(); |
92
|
|
|
|
93
|
|
|
// Parent class Base62 explain time parts different, so get raw again |
94
|
|
|
$second = substr($uuid, 0, static::LENGTH_SECOND); |
95
|
|
|
$position = static::LENGTH_SECOND + strlen(static::SEPARATOR); |
96
|
|
|
$microSecond = substr($uuid, $position, static::LENGTH_MICROSECOND); |
97
|
|
|
|
98
|
|
|
$timeStr = $second . $microSecond; |
99
|
|
|
$timeStr = $converter->convert($timeStr, 62, 10); |
100
|
|
|
|
101
|
|
|
$second = round($timeStr / 1000000) + static::TIMESTAMP_OFFSET; |
102
|
|
|
$second = date('Y-m-d H:i:s', $second); |
103
|
|
|
|
104
|
|
|
$microsecond = strval(round($timeStr % 1000000)); |
105
|
|
|
|
106
|
|
|
$explanation->setSecond($second) |
107
|
|
|
->setMicrosecond($microsecond); |
108
|
|
|
|
109
|
|
|
return $explanation; |
110
|
|
|
} |
111
|
|
|
|
112
|
|
|
|
113
|
|
|
/** |
114
|
|
|
* {@inheritdoc} |
115
|
|
|
*/ |
116
|
|
|
protected function generateRandomPart() |
117
|
|
|
{ |
118
|
|
|
$random = parent::generateRandomPart(); |
119
|
|
|
|
120
|
|
|
$random = substr($random, 0, static::LENGTH_RANDOM); |
121
|
|
|
|
122
|
|
|
return $random; |
123
|
|
|
} |
124
|
|
|
|
125
|
|
|
|
126
|
|
|
/** |
127
|
|
|
* {@inheritdoc} |
128
|
|
|
*/ |
129
|
|
|
protected function generateTimeParts() |
130
|
|
|
{ |
131
|
|
|
list($microSecond, $second) = explode(' ', microtime()); |
132
|
|
|
|
133
|
|
|
$microSecond = round($microSecond * 1000000); |
134
|
|
|
$microSecond = str_pad($microSecond, 6, '0', STR_PAD_LEFT); |
135
|
|
|
|
136
|
|
|
$converter = $this->getBaseConverter(); |
137
|
|
|
|
138
|
|
|
$timestamp = strval($second - static::TIMESTAMP_OFFSET) . $microSecond; |
139
|
|
|
$timeStr = $converter->convert($timestamp, 10, 62); |
140
|
|
|
|
141
|
|
|
return [ |
142
|
|
|
substr($timeStr, 0, static::LENGTH_SECOND), |
143
|
|
|
substr($timeStr, static::LENGTH_SECOND, static::LENGTH_MICROSECOND), |
144
|
|
|
]; |
145
|
|
|
} |
146
|
|
|
} |
147
|
|
|
|
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.
The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.
This check looks for comments that seem to be mostly valid code and reports them.