forked from zekroTJA/snowflake-js
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsnowflake.js
More file actions
122 lines (107 loc) · 2.93 KB
/
Copy pathsnowflake.js
File metadata and controls
122 lines (107 loc) · 2.93 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
// Epoch defaultly set to creation of this class
// (Tue Oct 23 2018 06:27:17 UTC)
const defEpoch = BigInt(1540276037951);
const nodeBits = BigInt(10);
const stepBits = BigInt(12);
const nodeMax = BigInt(BigInt(-1) ^ (BigInt(-1) << nodeBits));
const nodeMask = BigInt(nodeMax << stepBits);
const stepMask = BigInt(BigInt(-1) ^ (BigInt(-1) << stepBits));
const timeShift = nodeBits + stepBits;
const nodeShift = stepBits;
var epoch = defEpoch;
/**
* Node collection of Snowflakes.
*/
class Node {
/**
* Create instance of Node.
* @param {number} n Number of node
*/
constructor(n) {
n = parseInt(n);
if (!n || isNaN(n)) {
n = BigInt(0);
} else {
n = BigInt(n);
}
if (n < 0 || n > nodeMax) {
throw 'Node must be between 0 and ' + nodeMax;
}
this.time = BigInt(0);
this.step = BigInt(0);
this.n = n;
}
/**
* Generate Snowflake.
* @returns {BigInteger} Snowflake
*/
next() {
let now = BigInt(Date.now());
if (this.time == now) {
this.step = (this.step + BigInt(1)) & stepMask;
if (this.step == 0) {
while (now <= this.time) {
now = BigInt(Date.now());
}
}
} else {
this.step = BigInt(0);
}
this.time = now;
return (
((now - epoch) << timeShift) |
(this.n << nodeShift) |
(this.step)
);
}
}
/**
* Set the epoch where the snowflakes time count will strat from.
* @param {Date|number} date Epoche starting time counting from.
*/
function setEpoch(date) {
if (!date) {
epoch = BigInt(Date.now());
} else if (date instanceof Date) {
epoch = BigInt(date.getTime());
} else {
epoch = BigInt(date);
}
}
/**
* Get UNIX timestamp when snowflake was created.
* @param {number} snowflake Snowflake
* @param {Date|number} customEpoch Custom epoche date or number
* @returns {number} UNIX timestamp
*/
function getTimestamp(snowflake, customEpoch) {
if (customEpoch && customEpoch instanceof Date) {
customEpoch = customEpoch.getTime();
}
customEpoch = customEpoch ? BigInt(customEpoch) : BigInt(epoch);
return parseInt(customEpoch + (BigInt(snowflake) >> timeShift));
}
/**
* Get node from which snowflake was created with.
* @param {number} snowflake Snowflake
* @returns {number} Number of node
*/
function getNode(snowflake) {
return parseInt((BigInt(snowflake) & nodeMask) >> nodeShift);
}
/**
* Get number of step which was passed in the same millisecond
* in the node instance while Snowflake was created.
* @param {number} snowflake Snowflake
* @returns {number} Number of step
*/
function getStep(snowflake) {
return parseInt(BigInt(snowflake) & stepMask);
}
module.exports = {
setEpoch,
getTimestamp,
getNode,
getStep,
Node
}