Snowflake.js (2900B)
1 'use strict'; 2 3 const Util = require('../util/Util'); 4 5 // Discord epoch (2015-01-01T00:00:00.000Z) 6 const EPOCH = 1420070400000; 7 let INCREMENT = 0; 8 9 /** 10 * A container for useful snowflake-related methods. 11 */ 12 class SnowflakeUtil { 13 constructor() { 14 throw new Error(`The ${this.constructor.name} class may not be instantiated.`); 15 } 16 17 /** 18 * A Twitter snowflake, except the epoch is 2015-01-01T00:00:00.000Z 19 * ``` 20 * If we have a snowflake '266241948824764416' we can represent it as binary: 21 * 22 * 64 22 17 12 0 23 * 000000111011000111100001101001000101000000 00001 00000 000000000000 24 * number of ms since Discord epoch worker pid increment 25 * ``` 26 * @typedef {string} Snowflake 27 */ 28 29 /** 30 * Generates a Discord snowflake. 31 * <info>This hardcodes the worker ID as 1 and the process ID as 0.</info> 32 * @param {number|Date} [timestamp=Date.now()] Timestamp or date of the snowflake to generate 33 * @returns {Snowflake} The generated snowflake 34 */ 35 static generate(timestamp = Date.now()) { 36 if (timestamp instanceof Date) timestamp = timestamp.getTime(); 37 if (typeof timestamp !== 'number' || isNaN(timestamp)) { 38 throw new TypeError( 39 `"timestamp" argument must be a number (received ${isNaN(timestamp) ? 'NaN' : typeof timestamp})`, 40 ); 41 } 42 if (INCREMENT >= 4095) INCREMENT = 0; 43 // eslint-disable-next-line max-len 44 const BINARY = `${(timestamp - EPOCH).toString(2).padStart(42, '0')}0000100000${(INCREMENT++) 45 .toString(2) 46 .padStart(12, '0')}`; 47 return Util.binaryToID(BINARY); 48 } 49 50 /** 51 * A deconstructed snowflake. 52 * @typedef {Object} DeconstructedSnowflake 53 * @property {number} timestamp Timestamp the snowflake was created 54 * @property {Date} date Date the snowflake was created 55 * @property {number} workerID Worker ID in the snowflake 56 * @property {number} processID Process ID in the snowflake 57 * @property {number} increment Increment in the snowflake 58 * @property {string} binary Binary representation of the snowflake 59 */ 60 61 /** 62 * Deconstructs a Discord snowflake. 63 * @param {Snowflake} snowflake Snowflake to deconstruct 64 * @returns {DeconstructedSnowflake} Deconstructed snowflake 65 */ 66 static deconstruct(snowflake) { 67 const BINARY = Util.idToBinary(snowflake) 68 .toString(2) 69 .padStart(64, '0'); 70 const res = { 71 timestamp: parseInt(BINARY.substring(0, 42), 2) + EPOCH, 72 workerID: parseInt(BINARY.substring(42, 47), 2), 73 processID: parseInt(BINARY.substring(47, 52), 2), 74 increment: parseInt(BINARY.substring(52, 64), 2), 75 binary: BINARY, 76 }; 77 Object.defineProperty(res, 'date', { 78 get: function get() { 79 return new Date(this.timestamp); 80 }, 81 enumerable: true, 82 }); 83 return res; 84 } 85 } 86 87 module.exports = SnowflakeUtil;