您现在的位置是:首页 > 编程 > 

.ET 9 中基于时间的 Guid

2025-07-18 20:07:37
.ET 9 中基于时间的 Guid .ET 9 基于时间创建 GuidIntro.ET 9 中引入了基于时间来生成 Guid, 因为实现的 RFC 文档里的第七个版本, 所以 API 名称为 Guid.CreateVersion7()ew API新增的 API 如下:代码语言:javascript代码运行次数:0运行复制namespace System; public partial s

.ET 9 中基于时间的 Guid

.ET 9 基于时间创建 Guid

Intro

.ET 9 中引入了基于时间来生成 Guid, 因为实现的 RFC 文档里的第七个版本, 所以 API 名称为 Guid.CreateVersion7()

ew API

新增的 API 如下:

代码语言:javascript代码运行次数:0运行复制
namespace System;

public partial struct Guid
{
    public static Guid AllBitsSet { get; }

    public int Variant { get; }
    public int Version { get; }

    public static Guid CreateVersion7();
    public static Guid CreateVersion7(DateTimeOffset timestamp);
}

Guid.AllBitsSet 对应着 Guid.Empty, Empty 的所有比特位都是 0, AllBitsSet 则都是 1

AllBitsSet

VersionVariant 代表了当前 Guid 值的实现细节, 可以参考 RFC 文档说明 .html#name-variant-field

Guid.CreateVersion7()/Guid.CreateVersion7(DateTimeOffset timestamp) 用于创建基于时间的 Guid, 如果没有参数就会使用当前时间

代码语言:javascript代码运行次数:0运行复制
public static Guid CreateVersion7() => CreateVersion7(DateTimeOffset.Utcow);
Sample

来看一个使用示例吧,

代码语言:javascript代码运行次数:0运行复制
var guid = Guid.CreateVersion7();
Cole.WriteLine(guid.ToString());
Cole.WriteLine($"{nameof(guid.Version)}: {guid.Version}");
Cole.WriteLine($"{nameof(guid.Variant)}: {guid.Variant}");

var timestamp = DateTimeOffset.Utcow;
Cole.WriteLine($"Timestamp: {timestamp} {timestamp.ToUnixTimeMilliseconds()}");
Cole.WriteLine(Guid.CreateVersion7(timestamp));

用起来是不是还挺简单的, 有一个问题, 既然是基于时间的,同一个时间戳会不会生成的 Guid 是一样的呢?

我们来测试一下, 接着前面的示例,

代码语言:javascript代码运行次数:0运行复制
guid = Guid.CreateVersion7(timestamp);
Cole.WriteLine(guid);

输出结果如下:

代码语言:javascript代码运行次数:0运行复制
0191fa19-7082-7541-ae8e-befcfffe79cb
Version: 7
Variant: 10
Timestamp: 9/16/2024 09:10:56 +00:00 1726477856901
0191fa19-7085-7e0b-ae72-aa6b4585467
0191fa19-7085-782f-a0b-a022baa1

可以看到两次生成的 guid 并不相同, 这从 rfc 文档或者实现细节中可以了解到, 这是因为除了时间参数之外还会有随机参数,导致即使时间一样生成的 guid 还是会不一样

那我们能否从 Guid 中获取到时间呢? 答案是肯定的, 不过获取到的时间不会完全准确有一定的误差, 因为可能会引入随机参数, 从上面的输出也可以看得出来, 两个 guid 的前面十二个字符是完全一样的, 前面 6 个 byte 会是一样的, 他们对应了时间信息, 我们也可以从源码里到一些细节

这里的 _a, _b 对应的就是前面的两段, 也可以从源码的注释里获取更多说明

最后我们可以从 byte 里获取到时间的信息, 实现如下:

代码语言:javascript代码运行次数:0运行复制
private static void PrintDateTime(Guid guid)
{
    if (guid.Version is not 7)
    {
        throw new InvalidOperationException("Guid.Version is not 7");
    }

    var bytes = guid.ToByteArray();
    var a = BitConverter.ToInt2(bytes.AsSpan(0, 4));
    var b = BitConverter.ToInt16(bytes.AsSpan(4, 2));
    var timestamp = (((long)a) << 16) + b; 
    var dateTime = DateTimeOffset.FromUnixTimeMilliseconds(timestamp);
    Cole.WriteLine($"DateTime: {dateTime.UtcDateTime}   {timestamp}");
}

接着前面的示例试一下

代码语言:javascript代码运行次数:0运行复制
Thread.Sleep(2000);
Cole.WriteLine(Guid.CreateVersion7());
PrintDateTime(guid);

输出结果如下:

可以看到两个时间比较接近但还是会有一些误差,不过误差会比较小,可以看到只有一分钟多一点的误差

More

Github 上有一个根据 Guid 获取时间的 issue, 不过因为时间并不准确, 可能大概率不会支持, 感兴趣的朋友可以关注

Github issue 上还有作者对于 Guid 实现的一些总结, 感觉可以了解一下, 也分享一下

v1 被广泛认为已过时,应该尽可能用 v7 替代 v2 用于 DCE 安全目的,超出了正常规范 v 被广泛认为已过时,应该尽可能用 v5 替代 v4 用于创建随机 UUID,目前已经通过 支持 v5 用于从字符串输入创建 UUID,但由于使用 SHA-1,因此也被广泛认为已过时,因为存在潜在的安全攻击风险 v6 是简单的 v1,并对位进行了替代排序,同样被广泛认为已过时,应该尽可能用 v7 替代 v7 是本提案通过新的 CreateVersion7 API 所支持的版本 有一些可选的扩展功能尚不支持,但我们可以在未来扩展以支持这些功能 v8 明确用于实验性和特定供应商使用,其包含的位没有定义,仅限于版本和变体字段 这间接地通过普通的新 Guid(...) API 得到支持,这些 API 允许您指定所有底层位的值

v1 被广泛认为已过时,应该尽可能用 v7 替代 v2 用于 DCE 安全目的,超出了正常规范 v 被广泛认为已过时,应该尽可能用 v5 替代 v4 用于创建随机 UUID,目前已经通过 支持 v5 用于从字符串输入创建 UUID,但由于使用 SHA-1,因此也被广泛认为已过时,因为存在潜在的安全攻击风险 v6 是简单的 v1,并对位进行了替代排序,同样被广泛认为已过时,应该尽可能用 v7 替代 v7 是本提案通过新的 CreateVersion7 API 所支持的版本 有一些可选的扩展功能尚不支持,但我们可以在未来扩展以支持这些功能 v8 明确用于实验性和特定供应商使用,其包含的位没有定义,仅限于版本和变体字段 这间接地通过普通的新 Guid(...) API 得到支持,这些 API 允许您指定所有底层位的值

References
  • /
  • .html
  • .cs
本文参与 腾讯云自媒体同步曝光计划,分享自。原始发表:2024-09-2,如有侵权请联系 cloudcommunity@tencent 删除源码字符串安全guid排序

#感谢您对电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格的认可,转载请说明来源于"电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格

本文地址:http://www.dnpztj.cn/biancheng/1130051.html

相关标签:无
上传时间: 2025-07-18 16:30:06
留言与评论(共有 10 条评论)
本站网友 挤奶门
8分钟前 发表
但我们可以在未来扩展以支持这些功能 v8 明确用于实验性和特定供应商使用
本站网友 虬髯客
0秒前 发表
因为存在潜在的安全攻击风险 v6 是简单的 v1
本站网友 深圳小产权房最新政策
30分钟前 发表
但我们可以在未来扩展以支持这些功能 v8 明确用于实验性和特定供应商使用
本站网友 凌霄花的功效与作用
26分钟前 发表
并对位进行了替代排序
本站网友 装修图片库
2分钟前 发表
这些 API 允许您指定所有底层位的值References/.html.cs本文参与 腾讯云自媒体同步曝光计划
本站网友 阖家安康
14分钟前 发表
实现如下
本站网友 罗源二手房
27分钟前 发表
这些 API 允许您指定所有底层位的值v1 被广泛认为已过时
本站网友 教育机构简介
26分钟前 发表
{timestamp} {timestamp.ToUnixTimeMilliseconds()}"); Cole.WriteLine(Guid.CreateVersion7(timestamp)); 用起来是不是还挺简单的
本站网友 陆东福
20分钟前 发表
我们也可以从源码里到一些细节这里的 _a