Generate short unique identifier in .NET apps

I was reading a Stackoverflow question about generating short unique identifiers in C# and saw people are using baseline date time and time difference for ID generation. I really like the idea and wondered how that could be shortened even more.

After some attempts, I found it is possible to use a combination of Unix epoch and a counter to make a short unique identifier with only 11 characters.

// This is the counter for current epoch. Counter should reset in next millisecond
ushort currentCounter = 123;

var epoch = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
// Because epoch is 64bit long, so we should have 8 bytes
var epochBytes = BitConverter.GetBytes(epoch);
if (BitConverter.IsLittleEndian)
{
    // Use big endian
    epochBytes = epochBytes.Reverse().ToArray();
}

// The first two bytes are always 0, because if not, the DateTime.UtcNow is greater 
// than DateTime.Max, which is not possible
var counterBytes = BitConverter.GetBytes(currentCounter);
if (BitConverter.IsLittleEndian)
{
    // Use big endian
    counterBytes = counterBytes.Reverse().ToArray();
}

// Copy counter bytes to the first 2 bytes of the epoch bytes
Array.Copy(counterBytes, 0, epochBytes, 0, 2);

// Encode the byte array and trim padding '='
var shortUid = Convert.ToBase64String(epochBytes).TrimEnd('=');

How this works?

Unix epoch in C#  is represented as a long 64-bit integer value. Due to the range of DateTime in C#, the first 2 bytes of the 8 bytes of the 64-bit value are always 0. So that gives us 2 bytes to place a counter value in.

The best choice here is an unsigned short value, with a range from 0 to 65535, giving us 65536 unique IDs per epoch value. In another word, as long as the number of ID generation does not exceed 65536 per millisecond, this approach should work.

The final ID is base64 encoded string representation of the generated long integer. With Base64, 8 bytes will be encoded to 12 characters, including 1 padding "=" sign. We could trim that sign to make the ID only contain 11 characters.

Comments