// Copyright (c) Tribufu. All Rights Reserved. // SPDX-License-Identifier: UNLICENSED using IdGen; using System; namespace Tribufu.Platform { public static class FlakeGenerator { public static readonly DateTime EPOCH = new(2016, 1, 1, 0, 0, 0, DateTimeKind.Utc); private static readonly IdStructure _structure = new(41, 10, 12); private static readonly IdGeneratorOptions _options = new(_structure, new DefaultTimeSource(EPOCH)); private static readonly IdGenerator _generator = new(0, _options); public static ulong New() { //Console.WriteLine("Max. generators : {0}", _structure.MaxGenerators); //Console.WriteLine("Id's/ms per generator : {0}", _structure.MaxSequenceIds); //Console.WriteLine("Id's/ms total : {0}", _structure.MaxGenerators * _structure.MaxSequenceIds); //Console.WriteLine("Wraparound interval : {0}", _structure.WraparoundInterval(_generator.Options.TimeSource)); //Console.WriteLine("Wraparound date : {0}", _structure.WraparoundDate(_generator.Options.TimeSource.Epoch, _generator.Options.TimeSource).ToString("O")); return (ulong)_generator.CreateId(); } public static ulong FromTimestamp(DateTime timestamp, ushort sequence = 0) { var diff = (long)(timestamp - EPOCH).TotalMilliseconds; if (diff < 0 || diff > (1L << 41) - 1) { throw new ArgumentOutOfRangeException(nameof(timestamp), "Timestamp out of range for flake."); } ulong timestampPart = (ulong)diff << 22; // 41 bits << (10+12) ulong generatorPart = 0ul << 12; // Always 0 ulong sequencePart = (ulong)(sequence & 0xFFF); // 12 bits return timestampPart | generatorPart | sequencePart; } } }