uuid-cbr 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +33 -0
- package/index.js +149 -0
- package/package.json +9 -0
- package/test.js +21 -0
package/README.md
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# UUID-CBR
|
|
2
|
+
|
|
3
|
+
> Js библиотека для генирации uuid по требованию ЦБ
|
|
4
|
+
|
|
5
|
+
### Пример использования
|
|
6
|
+
|
|
7
|
+
**_Генерация uuid_**
|
|
8
|
+
|
|
9
|
+
```JavaScript
|
|
10
|
+
const { generate } = require("uuid-cbr");
|
|
11
|
+
const nowDatetime = new Date("2021-09-24T09:55:09.332Z")
|
|
12
|
+
const uuidByDate = generate(nowDatetime)
|
|
13
|
+
console.log(uuidByDate); // 80c57a90-1d1d-11ec-adda-26dbb65f1526-0
|
|
14
|
+
|
|
15
|
+
const uuidNowDate = generate()
|
|
16
|
+
console.log(uuidNowDate); // 3ce3d880-1d1e-11ec-b690-d07329e2e226-5
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
**_Проверка валидации_**
|
|
20
|
+
|
|
21
|
+
```JavaScript
|
|
22
|
+
const { isValid } = require("uuid-cbr");
|
|
23
|
+
const isValidUUID = isValid('3ce3d880-1d1e-11ec-b690-d07329e2e226-5')
|
|
24
|
+
console.log(isValidUUID) //true
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
**_Преобразование uuid к дате_**
|
|
28
|
+
|
|
29
|
+
```JavaScript
|
|
30
|
+
const { toDate } = require("uuid-cbr");
|
|
31
|
+
const datetime = toDate('80c57a90-1d1d-11ec-adda-26dbb65f1526-0')
|
|
32
|
+
console.log(datetime) //2021-09-24T09:55:09.332Z
|
|
33
|
+
```
|
package/index.js
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
const crypto = require("crypto");
|
|
2
|
+
const winEpoch = new Date("01-01-1601 UTC").getTime();
|
|
3
|
+
|
|
4
|
+
const random = (min, max) => {
|
|
5
|
+
return Math.floor(Math.random() * (max - min + 1) + min);
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
let gLastUSNS = 0;
|
|
9
|
+
let gLastTime = 0;
|
|
10
|
+
let time = 0;
|
|
11
|
+
|
|
12
|
+
const getTime = (datetime) => {
|
|
13
|
+
do {
|
|
14
|
+
const winDate = (new Date(datetime).getTime() - winEpoch) * 10000;
|
|
15
|
+
time = winDate + 5748192000000000;
|
|
16
|
+
} while (time === gLastTime && gLastUSNS === 9999);
|
|
17
|
+
|
|
18
|
+
if (time === gLastTime) {
|
|
19
|
+
// Если время не изменилось, за микро- и наносекунды
|
|
20
|
+
// возьмем предыдущее значение плюс один
|
|
21
|
+
gLastUSNS++;
|
|
22
|
+
} else {
|
|
23
|
+
// Если время изменилось, за микро- и наносекунды возьмём 0.
|
|
24
|
+
gLastUSNS = random(1, 10000);
|
|
25
|
+
// и запомним значение времени
|
|
26
|
+
gLastTime = time;
|
|
27
|
+
}
|
|
28
|
+
time += gLastUSNS;
|
|
29
|
+
return time;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const calcCtrl = (uuid) => {
|
|
33
|
+
let pos = 0;
|
|
34
|
+
let index = 1;
|
|
35
|
+
let sum = 0;
|
|
36
|
+
while (uuid[pos]) {
|
|
37
|
+
const c = uuid[pos++];
|
|
38
|
+
// если символ - десятичная цифра
|
|
39
|
+
if (/\d/.test(c)) {
|
|
40
|
+
// увеличение суммы и индекса
|
|
41
|
+
sum += parseInt(c, 10) * index++;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// если символ - шестнадцатеричная цифра
|
|
45
|
+
if (/[a-f]/i.test(c)) {
|
|
46
|
+
sum += parseInt(c, 16) * index++;
|
|
47
|
+
}
|
|
48
|
+
// если значение индекса превысило 10, сбрасываем индекс в 1
|
|
49
|
+
if (index > 10) index = 1;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const r = sum % 16;
|
|
53
|
+
// возврат результата в виде контрольного символа
|
|
54
|
+
if (r < 10) {
|
|
55
|
+
return r;
|
|
56
|
+
}
|
|
57
|
+
return r.toString(16);
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
const isValid = (data) => {
|
|
61
|
+
const res = data.match(/^([0-9a-f]{8}-[0-9a-f]{4}-1[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12})-([0-9a-f]{1})$/);
|
|
62
|
+
if (!res) return false;
|
|
63
|
+
const [, uuid, cs] = res;
|
|
64
|
+
if (!uuid && !cs) {
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
return calcCtrl(uuid) == cs;
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
const bin2Hex = (bin) => {
|
|
71
|
+
const dec = parseInt(bin, 2);
|
|
72
|
+
const hex = dec.toString(16).padStart(4, "0");
|
|
73
|
+
return hex;
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
const gClockSeq = Buffer.alloc(14, crypto.randomBytes(14).readUInt32BE(0, true).toString(2));
|
|
77
|
+
const generate = (datetime = new Date()) => {
|
|
78
|
+
const gt = getTime(datetime);
|
|
79
|
+
|
|
80
|
+
const buff = Buffer.alloc(57, gt.toString(2));
|
|
81
|
+
|
|
82
|
+
const version_time_hide = Buffer.from(buff.buffer, 0, 9); // Из-за смещения 3ех нулей беру 9 байт
|
|
83
|
+
|
|
84
|
+
const clockseq_low = Buffer.from(gClockSeq.buffer, 6);
|
|
85
|
+
const variant_clockseq_high = Buffer.from(gClockSeq.buffer, 0, 6);
|
|
86
|
+
|
|
87
|
+
const time_low = Buffer.from(buff.buffer, 25);
|
|
88
|
+
|
|
89
|
+
const time_mid = Buffer.from(buff.buffer, 9, 16);
|
|
90
|
+
|
|
91
|
+
const time = {
|
|
92
|
+
time_bin: buff + "",
|
|
93
|
+
time_low: time_low + "",
|
|
94
|
+
time_mid: (time_mid + "").padStart(16, "0"),
|
|
95
|
+
version_time_hide: "0001000" + version_time_hide,
|
|
96
|
+
clockseq_low: `10${variant_clockseq_high.toString("binary")}${clockseq_low.toString("binary")}`,
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
const node = Buffer.alloc(6);
|
|
100
|
+
node[0] = crypto.randomBytes(4).readUInt32BE(0, true);
|
|
101
|
+
node[1] = crypto.randomBytes(4).readUInt32BE(0, true);
|
|
102
|
+
node[2] = crypto.randomBytes(4).readUInt32BE(0, true);
|
|
103
|
+
node[3] = crypto.randomBytes(4).readUInt32BE(0, true);
|
|
104
|
+
node[4] = crypto.randomBytes(4).readUInt32BE(0, true);
|
|
105
|
+
node[5] = crypto.randomBytes(4).readUInt32BE(0, true);
|
|
106
|
+
const result = [
|
|
107
|
+
bin2Hex(time.time_low).padStart(8, "0"),
|
|
108
|
+
bin2Hex(time.time_mid),
|
|
109
|
+
bin2Hex(time.version_time_hide),
|
|
110
|
+
bin2Hex(time.clockseq_low),
|
|
111
|
+
node.toString("hex"),
|
|
112
|
+
].join("-");
|
|
113
|
+
return result + "-" + calcCtrl(result);
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
const toDate = (uuid) => {
|
|
117
|
+
const [, time_low, time_mid, version_time_hide] = uuid.match(/^([0-9a-f]{8})-([0-9a-f]{4})-([0-9a-f]{4})-([0-9a-f]{4})/);
|
|
118
|
+
|
|
119
|
+
const bin_version_time_hide = parseInt(version_time_hide, 16)
|
|
120
|
+
.toString(2)
|
|
121
|
+
.replace(/^1000(.+)/, "$1");
|
|
122
|
+
const bin_time_mid = parseInt(time_mid, 16).toString(2).padStart(16, "0");
|
|
123
|
+
const bin_time_low = parseInt(time_low, 16).toString(2).padStart(32, "0");
|
|
124
|
+
|
|
125
|
+
const buff = Buffer.alloc(57, `${bin_version_time_hide}${bin_time_mid}${bin_time_low}`);
|
|
126
|
+
|
|
127
|
+
const nSec = parseInt(buff.toString("binary"), 2) - 5748192000000000;
|
|
128
|
+
return new Date(nSec / 10000 + winEpoch);
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
const info = (uuid) => {
|
|
132
|
+
const controlNum = uuid.split("-")[5];
|
|
133
|
+
|
|
134
|
+
return {
|
|
135
|
+
len: uuid.length,
|
|
136
|
+
valid: isValid(uuid),
|
|
137
|
+
controlNum,
|
|
138
|
+
gClockSeq: parseInt(gClockSeq.toString("hex"), 16),
|
|
139
|
+
datetime: toDate(uuid),
|
|
140
|
+
};
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
module.exports = {
|
|
144
|
+
generate,
|
|
145
|
+
isValid,
|
|
146
|
+
getTime,
|
|
147
|
+
toDate,
|
|
148
|
+
info,
|
|
149
|
+
};
|
package/package.json
ADDED
package/test.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
const { generate, isValid, info, toDate } = require("./index.js");
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
const nowDatetime = new Date("2021-09-24T09:55:09.332Z")
|
|
5
|
+
|
|
6
|
+
const uuid = generate(nowDatetime)
|
|
7
|
+
console.log(uuid)
|
|
8
|
+
|
|
9
|
+
const isValidUUID = isValid(uuid)
|
|
10
|
+
|
|
11
|
+
console.log(isValidUUID)
|
|
12
|
+
|
|
13
|
+
const infoUUID = info(uuid)
|
|
14
|
+
|
|
15
|
+
console.log(nowDatetime.toISOString(), infoUUID.datetime.toISOString())
|
|
16
|
+
console.assert(nowDatetime.toISOString() === infoUUID.datetime.toISOString())
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
const datetime = toDate('80c57a90-1d1d-11ec-adda-26dbb65f1526-0')
|
|
20
|
+
|
|
21
|
+
console.log(datetime)
|