I wanted to backport the Guid.CreateVersion7()
functionality (Version 7 UUID, RFC 9562) in the newer versions of .NET back into .NET Framework. This is that effort. I have tested the UUIDs generated at online validators here and here with success, so I am now looking for a review in terms of approach, clarity, performance, etc.
namespace UUIDv7
{
using System;
/// <summary>
/// Generate a Version 7 UUID as per RFC 9562.
/// </summary>
public static class Uuid7
{
private const byte Variant10xxMask = 0xC0;
private const byte Variant10xxValue = 0x80;
private const ushort VersionMask = 0xF000;
private const ushort Version7Value = 0x7000;
/// <summary>Creates a new <see cref="Guid" /> according to RFC 9562, following the Version 7 format.</summary>
/// <param name="timestamp">The optional date time offset used to determine the Unix Epoch timestamp.</param>
/// <returns>A new <see cref="Guid" /> according to RFC 9562, following the Version 7 format.</returns>
/// <exception cref="ArgumentOutOfRangeException"><paramref name="timestamp" /> represents an offset prior to
/// <see cref="DateTimeOffset" /> of zero.</exception>
public static Guid CreateVersion7(DateTimeOffset? timestamp = null)
{
long unix_ts_ms = (timestamp ?? DateTimeOffset.UtcNow).ToUnixTimeMilliseconds();
if (unix_ts_ms < 0L)
{
throw new ArgumentOutOfRangeException(nameof(timestamp), timestamp, "Cannot be negative.");
}
byte[] result = Guid.NewGuid().ToByteArray();
short resultC = (short)((result[4] << 8) + result[5]);
byte resultD = result[8];
int a = (int)(unix_ts_ms >> 16);
short b = (short)unix_ts_ms;
short c = (short)((resultC & ~VersionMask) | Version7Value);
byte d = (byte)((resultD & ~Variant10xxMask) | Variant10xxValue);
byte[] finalD = new byte[8];
finalD[0] = d;
Array.Copy(result, 9, finalD, 1, 6);
return new Guid(a, b, c, finalD);
}
}
}