Skip to content

Commit d294c0a

Browse files
committed
GPT-5 generated
1 parent 4ada8fd commit d294c0a

File tree

3 files changed

+159
-0
lines changed

3 files changed

+159
-0
lines changed

Timestamp48/TASK.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Timestamp 48 bit
2+
3+
- Implement 48 bit timestamp generator like in UUIDv7 standard
4+
- Encode generated id in Base64URL format

Timestamp48/gpt-5.js

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
'use strict';
2+
3+
const crypto = require('crypto');
4+
5+
const _state = {
6+
lastMs: 0n,
7+
seq12: 0,
8+
};
9+
10+
const _nowMs = () => BigInt(Date.now());
11+
const _waitNextMs = (currentMs) => {
12+
let t = _nowMs();
13+
while (t <= currentMs) t = _nowMs();
14+
return t;
15+
};
16+
17+
const _packUuidV7 = (ts48, seq12, randTail8) => {
18+
const buf = Buffer.allocUnsafe(16);
19+
20+
// 48-bit timestamp (big-endian)
21+
buf[0] = Number((ts48 >> 40n) & 0xffn);
22+
buf[1] = Number((ts48 >> 32n) & 0xffn);
23+
buf[2] = Number((ts48 >> 24n) & 0xffn);
24+
buf[3] = Number((ts48 >> 16n) & 0xffn);
25+
buf[4] = Number((ts48 >> 8n) & 0xffn);
26+
buf[5] = Number(ts48 & 0xffn);
27+
28+
// version (7) and high 4 bits of seq12
29+
buf[6] = 0x70 | ((seq12 >> 8) & 0x0f);
30+
31+
// low 8 bits of seq12
32+
buf[7] = seq12 & 0xff;
33+
34+
// 62 random bits with RFC 4122 variant (10xxxxxx)
35+
randTail8[0] = (randTail8[0] & 0x3f) | 0x80;
36+
randTail8.copy(buf, 8);
37+
38+
return buf;
39+
};
40+
41+
const _toBase64Url = (buf) =>
42+
buf
43+
.toString('base64')
44+
.replace(/\+/g, '-')
45+
.replace(/\//g, '_')
46+
.replace(/=+$/, '');
47+
48+
/**
49+
* Generates a UUIDv7-like 128-bit ID:
50+
* - 48-bit Unix ms timestamp
51+
* - version 7 nibble
52+
* - 12-bit monotonic sequence (per ms)
53+
* - variant (RFC 4122)
54+
* - 62 random tail bits
55+
* Encoded as Base64URL (22 chars).
56+
*/
57+
const generateV7Base64Url = () => {
58+
let ts = _nowMs();
59+
if (ts === _state.lastMs) {
60+
_state.seq12 = (_state.seq12 + 1) & 0x0fff;
61+
if (_state.seq12 === 0) ts = _waitNextMs(ts);
62+
} else {
63+
_state.seq12 = crypto.randomInt(0, 0x1000);
64+
}
65+
_state.lastMs = ts;
66+
67+
const tail = crypto.randomBytes(8);
68+
const bytes = _packUuidV7(ts, _state.seq12, tail);
69+
return _toBase64Url(bytes);
70+
};
71+
72+
module.exports = {
73+
generateV7Base64Url,
74+
};

Timestamp48/gpt-5.mjs

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
// uuidv7-web.mjs (ESM, browser-safe, arrow-only, monotonic, Base64URL)
2+
3+
// internal state (per module instance)
4+
const _state = {
5+
lastMs: 0n,
6+
seq12: 0,
7+
};
8+
9+
const _nowMs = () => BigInt(Date.now());
10+
const _random12 = () =>
11+
globalThis.crypto.getRandomValues(new Uint16Array(1))[0] & 0x0fff;
12+
const _randomTail8 = () => {
13+
const a = new Uint8Array(8);
14+
globalThis.crypto.getRandomValues(a);
15+
return a;
16+
};
17+
18+
const _packUuidV7 = (ts48, seq12, randTail8) => {
19+
const bytes = new Uint8Array(16);
20+
21+
// 48-bit timestamp (big-endian)
22+
bytes[0] = Number((ts48 >> 40n) & 0xffn);
23+
bytes[1] = Number((ts48 >> 32n) & 0xffn);
24+
bytes[2] = Number((ts48 >> 24n) & 0xffn);
25+
bytes[3] = Number((ts48 >> 16n) & 0xffn);
26+
bytes[4] = Number((ts48 >> 8n) & 0xffn);
27+
bytes[5] = Number(ts48 & 0xffn);
28+
29+
// version (7) and high 4 bits of seq12
30+
bytes[6] = 0x70 | ((seq12 >> 8) & 0x0f);
31+
32+
// low 8 bits of seq12
33+
bytes[7] = seq12 & 0xff;
34+
35+
// RFC 4122 variant on next 8 bytes (10xxxxxx)
36+
const tail = randTail8.slice(0);
37+
tail[0] = (tail[0] & 0x3f) | 0x80;
38+
bytes.set(tail, 8);
39+
40+
return bytes;
41+
};
42+
43+
const _toBase64Url = (bytes) => {
44+
let bin = '';
45+
for (let i = 0; i < bytes.length; i += 1) {
46+
bin += String.fromCharCode(bytes[i]);
47+
}
48+
return btoa(bin).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
49+
};
50+
51+
/**
52+
* Generates a UUIDv7-like 128-bit ID:
53+
* - 48-bit Unix ms timestamp
54+
* - version 7 nibble
55+
* - 12-bit monotonic sequence (per ms)
56+
* - RFC 4122 variant
57+
* - 62 random tail bits
58+
* Encoded as Base64URL (22 chars).
59+
*
60+
* Monotonic strategy (non-blocking):
61+
* on seq overflow within same ms, bump the virtual timestamp by +1 ms.
62+
*/
63+
export const generateV7Base64Url = () => {
64+
const now = _nowMs();
65+
let ts = now > _state.lastMs ? now : _state.lastMs;
66+
67+
if (ts === _state.lastMs) {
68+
_state.seq12 = (_state.seq12 + 1) & 0x0fff;
69+
if (_state.seq12 === 0) ts = _state.lastMs + 1n; // avoid busy-wait
70+
} else {
71+
_state.seq12 = _random12();
72+
}
73+
74+
_state.lastMs = ts;
75+
76+
const tail = _randomTail8();
77+
const bytes = _packUuidV7(ts, _state.seq12, tail);
78+
return _toBase64Url(bytes);
79+
};
80+
81+
export default generateV7Base64Url;

0 commit comments

Comments
 (0)