【问题标题】:How to generate guid from DateTime?如何从 DateTime 生成 guid?
【发布时间】:2018-09-18 15:38:06
【问题描述】:

我想从DateTime 生成 Guid v.1。我尝试使用此处描述的类:

https://gist.github.com/nberardi/3759706

但是在从Guid 获得DateTime 之后,我尝试使用DateTime 获得与原始Guid 相同的DateTime,它给了我一个不同的Guid。这是我使用的代码:

  string uuidString = "9e5713bb-bb4c-11e8-9d6c-12345678df23";
  Guid gui = new Guid(uuidString);
  DateTime dateTimeFromGuid = GuidGenerator.GetDateTime(gui);
  Console.WriteLine(dateTimeFromGuid.ToString("dd/MM/yyyy hh:mm:ss"));
  Guid guidFromDateTime = GuidGenerator.GenerateTimeBasedGuid(dateTimeFromGuid);
  Console.WriteLine(guidFromDateTime); //7909dbbb-bb33-11e8-9f6a-95d8e90ccf10

如何从 DateTime 取回原始 GUID?

【问题讨论】:

  • 你链接到的代码有一个方法可以做到这一点,你到底在问什么?
  • 它不......它对我来说非常好......见这里:dotnetfiddle.net/oQ9TTP(我只是复制/粘贴了要点和你的代码)。您可能正在做其他事情
  • @spender 我也看到 GUID 发生了变化,比如 Camilo
  • 对我来说,打印在 Fiddle 中的 Guid 每次运行都会改变。
  • 无法仅从日期/时间重建 GUID。查看源代码中的node 以了解您链接到的内容。

标签: c# datetime


【解决方案1】:

如果您想要一些简单的东西,无论您在什么机器上都可以来回转换。然后,您可以将日期转换为字节数组并使用它来创建Guid。这是非标准的,但会为每个 DateTime 生成完全相同的 Guid

var today = new DateTime(2018, 9, 18, 10, 59, 00);

var bytes = BitConverter.GetBytes(today.Ticks);

Array.Resize(ref bytes, 16);

var guid = new Guid(bytes);

Console.WriteLine(guid); //bd02b200-1d55-08d6-0000-000000000000

回到过去。

var dateBytes = guid.ToByteArray();

Array.Resize(ref dateBytes, 8);

var date = new DateTime(BitConverter.ToInt64(dateBytes));

Console.WriteLine(date); //9/18/2018 10:59:00

如果你想使用扩展那么。

class Program
{
    static void Main(string[] args)
    {
        var date = new DateTime(2018, 09, 18, 12, 00, 00);

        var guid = date.ToGuid();

        Console.WriteLine(guid); // 428a6000-1d5e-08d6-0000-000000000000

        var back2date = guid.ToDateTime();

        Console.WriteLine(back2date); // 9/18/2018 12:00:00
    }
}

public static class DateTimeExtensions
{
    public static Guid ToGuid(this DateTime dt)
    {
        var bytes = BitConverter.GetBytes(dt.Ticks);

        Array.Resize(ref bytes, 16);

        return new Guid(bytes);
    }
}

public static class GuidExtensions
{
    public static DateTime ToDateTime(this Guid guid)
    {
        var bytes = guid.ToByteArray();

        Array.Resize(ref bytes, 8);

        return new DateTime(BitConverter.ToInt64(bytes));
    }
}

【讨论】:

  • Guids/UUIDs have versioning info in them and follow standards。通过有效地将随机数据(或日期时间数据)塞入 Guid 的字节中,您正在创建非标准的东西。您还创建了一个 8 个零字节的 Guid。我不太确定。
  • 你可以从你的日期取回bd02b200-1d55-08d6-0000-00000000值?
  • DateTime 的值只有 8 个字节,因此您只需要 8 个字节即可从 Datetime 创建一个唯一的 Guid,该Datetime 将始终转换回来。
  • 从阅读有关版本控制的信息看来,这似乎只在使用分布式系统时才重要?这里还有其他风险吗? @spender ?
  • 因为我正在处理一个不关心创建节点或标准 guid 的任何其他元数据的记录,如果这个 guid 不是最安全的值,那也没关系。这对我的用例来说似乎是完全合理的。
【解决方案2】:

如果目标是获得可重现的 GUID,那么您需要禁用随机组件。这些是在程序启动时设置的。之后它们不再变化,因此生成的 GUID 从那时起就稳定了,但是程序的每次运行都会使用不同的随机值,因此每次运行都会为已知的日期时间值提供不同的半随机 GUID。

要禁用它,只需执行以下操作:

//var random = new Random();
//random.NextBytes(DefaultClockSequence);
//random.NextBytes(DefaultNode);

此外,在本地运行时,您必须强制 DateTime 值使用 UTC,我这样做如下:

DateTime dateTimeFromGuid = GuidGenerator.GetDateTime(gui);
dateTimeFromGuid = new DateTime(dateTimeFromGuid.Ticks, DateTimeKind.Utc);

将这个“UTC 修复”移动到库代码中会更好。

Fiddle(我还将输入 GUID 更改为“非随机”值):
https://dotnetfiddle.net/niIHlz

【讨论】:

  • 您在 PC 上获得了9e5713bb-bb4c-11e8 - .. 值?
  • 我注意到在本地运行时 GUID 存在差异,这是由时区引起的。如果您将时区强制为 UTC,那么无论时区如何,它都应该可以工作。查看更新。
  • 看起来像这样的情况,当每个刻度都可以改变输出 guid 时。对吗?
猜你喜欢
  • 2010-12-25
  • 2019-09-24
  • 2012-08-08
  • 2017-07-05
  • 1970-01-01
  • 1970-01-01
  • 2011-03-11
相关资源
最近更新 更多