From 9bc4ca38705025bba39de9a55d78a576a4599ad5 Mon Sep 17 00:00:00 2001 From: Sebastian Korotkiewicz Date: Tue, 6 Feb 2024 05:43:57 +0100 Subject: [PATCH] Initial commit --- .gitignore | 5 ++++ decode.js | 28 ++++++++++++++++++++ encode.js | 47 ++++++++++++++++++++++++++++++++++ index.js | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 155 insertions(+) create mode 100644 .gitignore create mode 100644 decode.js create mode 100644 encode.js create mode 100644 index.js diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..acc2ddb --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +a.js +b.js +c.js +d.js +decode_d.js \ No newline at end of file diff --git a/decode.js b/decode.js new file mode 100644 index 0000000..fb9395d --- /dev/null +++ b/decode.js @@ -0,0 +1,28 @@ +function decodeSnowflake(idStr) { + const id = BigInt(idStr); + const binary = id.toString(2).padStart(64, '0'); + + const timestampShift = 22n; + const machineIdShift = 12n; + const sequenceMask = 0xFFFn; // 12 bitów na sekwencję + + const timestamp = (id >> (timestampShift + machineIdShift)) & 0x1FFFFFFFFFFn; + const machineId = (id >> machineIdShift) & 0x3FFn; // 10 bitów na ID maszyny + const sequence = id & sequenceMask; + + // Upewnij się, że epoka jest taka sama, jak użyta do generowania Snowflake IDs + const epoch = BigInt(1288834974657); // Powinna być taka sama, jak w generatorze + const date = new Date(Number(epoch + (timestamp * 1000n))); + + return { + timestamp: date, + machineId: machineId.toString(), + sequence: sequence.toString(), + }; +} + +// Użycie +const idStr = '7160488856901390336'; // Przykładowy identyfikator Snowflake +const decoded = decodeSnowflake(idStr); +console.log(decoded); + diff --git a/encode.js b/encode.js new file mode 100644 index 0000000..0013b90 --- /dev/null +++ b/encode.js @@ -0,0 +1,47 @@ +class Snowflake { + constructor(machineId) { + if (machineId < 0 || machineId >= 1024) { + throw new Error('Machine ID must be in the range 0-1023.'); + } + + this.machineId = BigInt(machineId); + this.sequence = BigInt(0); + this.lastTimestamp = BigInt(-1); + + // Konfiguracja bitów: 41 bitów na czas, 10 bitów na ID maszyny, 12 bitów na sekwencję + this.timestampShift = 22n; + this.machineIdShift = 12n; + this.sequenceMask = 0xFFFn; // 4095 w dziesiętnym, BigInt + } + + generate() { + let timestamp = BigInt(Date.now()); + + if (timestamp === this.lastTimestamp) { + this.sequence = (this.sequence + 1n) & this.sequenceMask; + + if (this.sequence === 0n) { + while (timestamp <= this.lastTimestamp) { + timestamp = BigInt(Date.now()); + } + } + } else { + this.sequence = 0n; + } + + this.lastTimestamp = timestamp; + + const id = ((timestamp & 0x1FFFFFFFFFFn) << this.timestampShift) | + (this.machineId << this.machineIdShift) | + this.sequence; + + return id.toString(); // Zwraca string, ponieważ BigInt może być zbyt duży dla niektórych zastosowań + } +} + +// Użycie +const machineId = 1; // ID maszyny (0-1023) +const snowflake = new Snowflake(machineId); + +const id1 = snowflake.generate(); +console.log(id1); diff --git a/index.js b/index.js new file mode 100644 index 0000000..f2afc74 --- /dev/null +++ b/index.js @@ -0,0 +1,75 @@ +class Snowflake { + constructor(machineId) { + if (machineId < 0 || machineId >= 1024) { + throw new Error("Machine ID must be in the range 0-1023."); + } + + this.machineId = BigInt(machineId); + this.sequence = BigInt(0); + this.lastTimestamp = BigInt(-1); + + // Konfiguracja bitów: 41 bitów na czas, 10 bitów na ID maszyny, 12 bitów na sekwencję + this.timestampShift = 22n; + this.machineIdShift = 12n; + this.sequenceMask = 0xfffn; // 4095 w dziesiętnym, BigInt + } + + generate() { + let timestamp = BigInt(Date.now()); + + if (timestamp === this.lastTimestamp) { + this.sequence = (this.sequence + 1n) & this.sequenceMask; + + if (this.sequence === 0n) { + while (timestamp <= this.lastTimestamp) { + timestamp = BigInt(Date.now()); + } + } + } else { + this.sequence = 0n; + } + + this.lastTimestamp = timestamp; + + const id = + ((timestamp & 0x1ffffffffffn) << this.timestampShift) | + (this.machineId << this.machineIdShift) | + this.sequence; + + return id.toString(); // Zwraca string, ponieważ BigInt może być zbyt duży dla niektórych zastosowań + } +} + +function decodeSnowflake(idStr) { + const id = BigInt(idStr); + const binary = id.toString(2).padStart(64, "0"); + + const timestampShift = 22n; + const machineIdShift = 12n; + const sequenceMask = 0xfffn; // 12 bitów na sekwencję + + const timestamp = (id >> (timestampShift + machineIdShift)) & 0x1ffffffffffn; + const machineId = (id >> machineIdShift) & 0x3ffn; // 10 bitów na ID maszyny + const sequence = id & sequenceMask; + + // Upewnij się, że epoka jest taka sama, jak użyta do generowania Snowflake IDs + const epoch = BigInt(1288834974657); // Powinna być taka sama, jak w generatorze + const date = new Date(Number(epoch + timestamp * 1000n)); + + return { + timestamp: date, + machineId: machineId.toString(), + sequence: sequence.toString(), + }; +} + +// Użycie +const machineId = 1; // ID maszyny (0-1023) +const snowflake = new Snowflake(machineId); + +const id1 = snowflake.generate(); +console.log("encodeID", id1); + +const idStr = id1; // Przykładowy identyfikator Snowflake +const decoded = decodeSnowflake(idStr); +console.log("decodeID", decoded);