Skip to content

Instantly share code, notes, and snippets.

@niki-timofe
Last active March 13, 2024 18:55
Show Gist options
  • Save niki-timofe/c79402051a885ce1f0bd8c53eda425a1 to your computer and use it in GitHub Desktop.
Save niki-timofe/c79402051a885ce1f0bd8c53eda425a1 to your computer and use it in GitHub Desktop.
Convert GUID to ObjectID
public static class ObjectIdGuidExtensions
{
private const byte TimeBasedGuidVersion = 1;
private static readonly DateTimeOffset UuidEpoch = new(1582, 10, 15, 0, 0, 0, TimeSpan.Zero);
public static Guid ToGuid(this string objId)
{
var oIdSpan = new ReadOnlySpan<byte>(Convert.FromHexString(objId));
var timestamp = BinaryPrimitives.ReadUInt32BigEndian(oIdSpan[..4]);
var guidTimestamp = (ulong)(DateTimeOffset.FromUnixTimeSeconds(timestamp) - UuidEpoch).Ticks + oIdSpan[9];
var guidTimestampAndVersion = guidTimestamp + ((ulong)TimeBasedGuidVersion << 60);
var guidBytes = new byte[16];
var guidSpan = guidBytes.AsSpan();
BinaryPrimitives.WriteUInt64LittleEndian(guidSpan[..8], guidTimestampAndVersion);
guidSpan[8] = 1 << 7;
oIdSpan[10..12].CopyTo(guidSpan[9..11]);
oIdSpan[4..9].CopyTo(guidSpan[11..16]);
return new Guid(guidBytes);
}
public static string ToObjectId(this Guid g)
{
var guidSpan = new ReadOnlySpan<byte>(g.ToByteArray());
if (guidSpan[7] >> 4 != TimeBasedGuidVersion)
{
throw new ArgumentOutOfRangeException(nameof(g), "Поддерживаются только GUID версии 1.");
}
var guidTimestampAndVersion = BinaryPrimitives.ReadUInt64LittleEndian(guidSpan[..8]);
var guidTimestamp = guidTimestampAndVersion - ((ulong)TimeBasedGuidVersion << 60);
var ninthByte = (byte)(guidTimestamp % 1000);
var timestamp = (uint)(UuidEpoch + TimeSpan.FromTicks((long)(guidTimestamp - ninthByte))).ToUnixTimeSeconds();
var oIdBytes = new byte[12];
var oIdSpan = oIdBytes.AsSpan();
BinaryPrimitives.WriteUInt32BigEndian(oIdSpan[..4], timestamp);
guidSpan[11..16].CopyTo(oIdSpan[4..9]);
oIdSpan[9] = ninthByte;
guidSpan[9..11].CopyTo(oIdSpan[10..12]);
return Convert.ToHexString(oIdBytes).ToLower();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment