C# : How can I encode GUIDs to 11 character ids?

Like https://www.youtube.com/watch?v={id}

{id}:11characters

I try to use Convert.ToBase64String

string encoded = Convert.ToBase64String(guid.ToByteArray())
                .Replace("/", "_")
                .Replace("+", "-").Replace("=", "");

like this

The GUIDs is only reduced to 22 characters.

How can I encode GUIDs to 11 character ids?(or less 22 characters)

1 answer

  • answered 2020-03-31 12:06 weichch

    This is off topic answer but it might give you an ID with only 11 characters.

    In C# a long value has 64 bits, which if encoded with Base64, there will be 12 characters, including 1 padding =. If we trim the padding =, there will be 11 characters.

    One crazy idea here is we could use a combination of Unix Epoch and a counter for one epoch value to form a long value. The Unix Epoch in C# DateTimeOffset.ToUnixEpochMilliseconds is in long format, but the first 2 bytes of the 8 bytes are always 0, because otherwise the date time value will be greater than the maximum date time value. So that gives us 2 bytes to place an ushort counter in.

    So, in total, as long as the number of ID generation does not exceed 65536 per millisecond, we can have an unique ID:

    // 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('=');