{"id":16221888,"url":"https://github.com/zanaptak/idgenerator","last_synced_at":"2025-03-19T11:31:13.692Z","repository":{"id":143647667,"uuid":"209440112","full_name":"zanaptak/IdGenerator","owner":"zanaptak","description":"A unique id generator for .NET and Fable, using timestamp plus random data, with multiple strength and precision options. Flexible alternative to UUID/GUID.","archived":false,"fork":false,"pushed_at":"2021-08-13T23:14:38.000Z","size":156,"stargazers_count":8,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-02-28T18:33:42.782Z","etag":null,"topics":["dotnet","fable","generator","id","identifier","unique"],"latest_commit_sha":null,"homepage":"","language":"F#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zanaptak.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-09-19T01:56:16.000Z","updated_at":"2024-05-25T18:11:12.000Z","dependencies_parsed_at":null,"dependency_job_id":"6378246b-d8a6-4ef6-a46e-d8409e46c08e","html_url":"https://github.com/zanaptak/IdGenerator","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zanaptak%2FIdGenerator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zanaptak%2FIdGenerator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zanaptak%2FIdGenerator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zanaptak%2FIdGenerator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zanaptak","download_url":"https://codeload.github.com/zanaptak/IdGenerator/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243989109,"owners_count":20379648,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dotnet","fable","generator","id","identifier","unique"],"created_at":"2024-10-10T12:10:18.692Z","updated_at":"2025-03-19T11:31:13.686Z","avatar_url":"https://github.com/zanaptak.png","language":"F#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Zanaptak.IdGenerator\n\n[![GitHub](https://img.shields.io/badge/-github-gray?logo=github)](https://github.com/zanaptak/IdGenerator) [![NuGet](https://img.shields.io/nuget/v/Zanaptak.IdGenerator?logo=nuget)](https://www.nuget.org/packages/Zanaptak.IdGenerator)\n\nA unique id generator for [.NET](https://dotnet.microsoft.com/) and [Fable](https://fable.io/), using timestamp plus random data, with multiple strength and precision options. Flexible alternative to UUID/GUID.\n\n## Overview\n\nGenerates universally unique string ids consisting of a sortable timestamp component followed by randomly generated data. The generator can be configured for different size and precision levels.\n\n## Examples\n\n### Small id\n\n```\nBBBbpQsdtSqbSmrJ\n[-time-][random]\n```\n\n### Medium id (default)\n\n```\nBBBbpQsdjMjrqhJxZPDhSstF\n[-time-][----random----]\n```\n\n### Large id\n\n```\nBBBbpQsdXsrJpKJdtCTNhCBsmfzqXrTb\n[-time-][--------random--------]\n```\n\n### Extra large id\n\n```\nBBBbpQsdNpBXhNNrRscZkSZJXNhTmMmTHJRhrZMx\n[-time-][------------random------------]\n```\n\n## Properties\n\n### Size, resolution, and bit distribution\n\n|   | String length | Time resolution | Time bits | Random bits | Total bits |\n| --- | :---: | :---: | :---: | :---: | :---: |\n| **Small**       | 16 characters | 3.3 ms | 40 | 40  | 80  |\n| **Medium**      | 24 characters | 3.3 ms | 40 | 80  | 120 |\n| **Large**       | 32 characters | 3.3 ms | 40 | 120 | 160 |\n| **Extra Large** | 40 characters | 3.3 ms | 40 | 160 | 200 |\n\n### Timestamp\n\n* The default 40 bit timestamp has approximately 3.3 millisecond resolution. That is, ids generated within the same 3.3 ms interval will have the same timestamp component. It has a range of over 114 years before cycling, good until the year 2133 (starting from 2019).\n* The time precision is configurable to increase or decrease the resolution, trading off random bits to do so. See [Adjustable time precision](#adjustable-time-precision).\n\n### Random data\n\n* The random data portion is generated from a cryptographic source when available, for improved statistical quality.\n  * For .NET, [`Cryptography.RandomNumberGenerator`](https://docs.microsoft.com/en-us/dotnet/api/system.security.cryptography.randomnumbergenerator?view=netstandard-2.0) is used.\n  * For Fable, [`window.crypto.getRandomValues`](https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues) is used if available, otherwise falling back to `Math.random`.\n    * When compiling a Node.js app with Fable, set the `ZANAPTAK_NODEJS_CRYPTO` compilation symbol to use [`crypto.randomFillSync`](https://nodejs.org/api/crypto.html#crypto_crypto_randomfillsync_buffer_offset_size) instead of `Math.random`.\n\n### String format\n\n* The id is formatted as a base 32 encoded string; each text character represents 5 bits of binary data.\n* Custom base 32 character set consisting of: `BCDFHJKMNPQRSTXZbcdfhjkmnpqrstxz`\n  * Digits and several confusable characters are excluded.\n  * Vowels and vowel-like characters are excluded to reduce the chance of accidental word patterns.\n  * Case-sensitive.\n* Ids will sort in increasing timestamp order when using ordinal string sort.\n\n## Adjustable time precision\n\nThe timestamp is based on the number of 100 nanosecond intervals (ticks) since a fixed epoch date of 2019-09-19 00:00:00 UTC, masked to the low 55 bits. This provides a range of just over 114 years. (100 ns * 2\u003csup\u003e55\u003c/sup\u003e = 3602879702 seconds = about 114.17 years)\n\nDepending on the desired precision, the high 32, 40, or 48 bits of that value are stored at the beginning of the generated id in big-endian order.\n\nThe number of random bits used in the id are adjusted depending on the precision to maintain a consistent overall string length.\n\n### Microsecond precision\n\n48 bit timestamp, approximately 13 microsecond resolution. (100 ns * 2\u003csup\u003e55\u003c/sup\u003e / 2\u003csup\u003e48\u003c/sup\u003e = 12.8 us)\n\n|   | String length | Time resolution | Time bits | Random bits | Total bits |\n| --- | :---: | :---: | :---: | :---: | :---: |\n| **Small**       | 16 characters | 13 us | 48 | 32  | 80  |\n| **Medium**      | 24 characters | 13 us | 48 | 72  | 120 |\n| **Large**       | 32 characters | 13 us | 48 | 112 | 160 |\n| **Extra Large** | 40 characters | 13 us | 48 | 152 | 200 |\n\n### Millisecond precision (default)\n\n40 bit timestamp, approximately 3.3 millisecond resolution. (100 ns * 2\u003csup\u003e55\u003c/sup\u003e / 2\u003csup\u003e40\u003c/sup\u003e = 3.2768 ms)\n\n|   | String length | Time resolution | Time bits | Random bits | Total bits |\n| --- | :---: | :---: | :---: | :---: | :---: |\n| **Small**       | 16 characters | 3.3 ms | 40 | 40  | 80  |\n| **Medium**      | 24 characters | 3.3 ms | 40 | 80  | 120 |\n| **Large**       | 32 characters | 3.3 ms | 40 | 120 | 160 |\n| **Extra Large** | 40 characters | 3.3 ms | 40 | 160 | 200 |\n\n### Second precision\n\n32 bit timestamp, approximately 0.84 second resolution. (100 ns * 2\u003csup\u003e55\u003c/sup\u003e / 2\u003csup\u003e32\u003c/sup\u003e = 0.8388608 s)\n\n|   | String length | Time resolution | Time bits | Random bits | Total bits |\n| --- | :---: | :---: | :---: | :---: | :---: |\n| **Small**       | 16 characters | 0.84 s | 32 | 48  | 80  |\n| **Medium**      | 24 characters | 0.84 s | 32 | 88  | 120 |\n| **Large**       | 32 characters | 0.84 s | 32 | 128 | 160 |\n| **Extra Large** | 40 characters | 0.84 s | 32 | 168 | 200 |\n\n### Notes\n\n* Time precision is subject to the system clock resolution of the target environment. The extra bits for a more precise timestamp will be wasted if the system clock does not update at that resolution.\n* The precision options do not affect the initial bits of the timestamp. The same first 32 bits of the timestamp are used regardless of precision, so the first 6 characters (30 encoded bits) of an id will be consistent under any precision option.\n* In Fable, timestamps are subject to the 1 ms date resolution of JavaScript rather than the 100 ns tick resolution of .NET. Therefore, in Fable:\n  * The Microsecond precision option has reduced effectiveness since multiple 13 us intervals can resolve to the same 1 ms timestamp.\n  * Extracting dates from ids will not produce an exact result since conversion to milliseconds will discard up to 9999 ticks of the encoded value. The exact tick value can be extracted accurately with `ExtractTicks`, but will still lose the extra tick precision if subsequently converted to a date in Fable.\n\n\n## Usage\n\nAdd the [NuGet package](https://www.nuget.org/packages/Zanaptak.IdGenerator) to your project:\n\n```\ndotnet add package Zanaptak.IdGenerator\n```\n\n### C#\n\n```cs\nusing Zanaptak.IdGenerator;\n\n// Create a generator instance\nvar idGenerator = new IdGenerator();\n\n// Generate an id\nvar myId = idGenerator.Next();\n\n// Get the timestamp from an id as a DateTimeOffset\nvar date = IdGenerator.ExtractDate(myId);\n\n// Create a generator instance for Small ids\nvar idGenSmall = new IdGenerator(IdSize.Small);\n\n// Create a generator instance for Large ids using Microsecond time precision\nvar idGenLargeMicro = new IdGenerator(IdSize.Large, IdTimePrecision.Microsecond);\n\n// Create a generator that buffers 100 random data blocks between calls to the crypto RNG source\nvar idGenWithBuffer = new IdGenerator(bufferCount: 100);\n```\n\n### F#\n\n```fs\nopen Zanaptak.IdGenerator\n\n// Create a generator instance\nlet idGenerator = IdGenerator()\n\n// Generate an id\nlet myId = idGenerator.Next()\n\n// Get the timestamp from an id as a DateTimeOffset\nlet date = IdGenerator.ExtractDate(myId)\n\n// Create a generator instance for Small ids\nlet idGenSmall = IdGenerator(IdSize.Small)\n\n// Create a generator instance for Large ids using Microsecond time precision\nlet idGenLargeMicro = IdGenerator(IdSize.Large, IdTimePrecision.Microsecond)\n\n// Create a generator that buffers 100 random data blocks between calls to the crypto RNG source\nlet idGenWithBuffer = IdGenerator(bufferCount=100)\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzanaptak%2Fidgenerator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzanaptak%2Fidgenerator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzanaptak%2Fidgenerator/lists"}