using System.Security.Cryptography; namespace Fleet.Core; /// 26 个字符的 ULID(Crockford base32,前 48 位为毫秒时间戳),按时间可排序。 public static class Ulid { private const string Alphabet = "0123456789ABCDEFGHJKMNPQRSTVWXYZ"; public static string New(TimeProvider time) { long ms = time.GetUtcNow().ToUnixTimeMilliseconds(); Span random = stackalloc byte[10]; RandomNumberGenerator.Fill(random); Span chars = stackalloc char[26]; for (int i = 9; i >= 0; i--) { chars[i] = Alphabet[(int)(ms & 31)]; ms >>= 5; } // 80 位随机数 → 16 个 base32 字符 UInt128 r = 0; foreach (byte b in random) { r = (r << 8) | b; } for (int i = 25; i >= 10; i--) { chars[i] = Alphabet[(int)(r & 31)]; r >>= 5; } return new string(chars); } /// 带类型前缀的 ID,例如 agt_01J…。 public static string NewPrefixed(string prefix, TimeProvider time) => prefix + "_" + New(time); }