【问题标题】:how do i get the date/time back from a UUID type 1我如何从 UUID 类型 1 中获取日期/时间
【发布时间】:2018-12-09 13:28:17
【问题描述】:

我已经包含了以下 UUID 库

compile group: 'com.fasterxml.uuid', name: 'java-uuid-generator', version: '3.1.5'

在我的构建中。

我有一些这样的代码

        NoArgGenerator timeBasedGenerator = Generators.timeBasedGenerator()
        UUID tuid = timeBasedGenerator.generate()
        Timestamp timestamp = new Timestamp ((tuid.timestamp()/1000) as Long)
        Date dateTime = new Date (timestamp.getTime())

但是,当我尝试查看日期时,它与应有的日期完全不同,例如,当今天是 30/06/2018 时,我得到 uid fef57eca-7c8b-11e8-bedd-992c2ac3197a was Sun Feb 06 07:55:54 GMT 6327

有谁知道如何使用fasterxml.uuid 库从基于时间的 UUID 中正确提取实际日期和时间?

但被难住了

ps 尝试了这个

        UUID tuid = timeBasedGenerator.generate()
        Long t = tuid.timestamp()
        Timestamp timestamp = new Timestamp (t)
        Date dateTime = new Date (timestamp.getTime())

它给出了一个 uid ff79d7d9-7cb5-11e8-976c-6ba57a5e9636Thu Aug 14 11:11:40 BST 4359073 的日期

【问题讨论】:

  • 您是否阅读过关于 1 类 UUID 结构的广泛可用的(即维基百科)文档?这会告诉你时间戳在哪里,剩下的就是编写代码来提取它。
  • Universally unique identifier。特别注意“格式”和“编码”部分
  • 为什么你认为Java的UUID的时间戳表示为时间戳单位的千分之一,而UUID和Java的纪元时刻是一样的呢?您是否验证了这些相当幼稚的假设?
  • 好吧并没有完全帮助 - 该库有一个称为时间戳的方法。我读到了这个docs.oracle.com/javase/7/docs/api/java/sql/Timestamp.html,它说它可以达到纳秒 - 所以除以 1000 似乎是合适的。我并没有尝试按照规范进行大量复杂的处理——当然,图书馆正在消除我的痛苦。所以肯定 timestamp() 调用 UUID 会返回非秒的时间吗?
  • 所以我在库中读取函数 aka timestamp() 的名称并没有按照它的建议 - 所以使用 UUID.timestamp() 方法返回我应该得到正确的时间背部 ?见上面添加的 PS

标签: java timeuuid


【解决方案1】:

我在网上进行了更多搜索。

我构建了以下可以根据需要扩展的“简单实用程序”类:

import com.fasterxml.uuid.Generators
import com.fasterxml.uuid.NoArgGenerator

class UuidUtil {

    static final NoArgGenerator timeBasedGenerator = Generators.timeBasedGenerator()


    /**
     * From UUID javadocs the resulting timestamp is measured in 100-nanosecond units since midnight, October 15, 1582 UTC
     * timestamp() from UUID is measured in 100-nanosecond units since midnight, October 15, 1582 UTC
     *
     * The Java timestamp in milliseconds since 1970-01-01 as baseline
     *
     * @return
     */
    static long getStartOfUuidRelativeToUnixEpochInMilliseconds () {
        Calendar c = Calendar.getInstance(TimeZone.getTimeZone("GMT-0"))
        c.set(Calendar.YEAR, 1582)
        c.set(Calendar.MONTH, Calendar.OCTOBER)
        c.set(Calendar.DAY_OF_MONTH, 15)
        c.set(Calendar.HOUR_OF_DAY, 0)
        c.set(Calendar.MINUTE, 0)
        c.set(Calendar.SECOND, 0)
        c.set(Calendar.MILLISECOND, 0)

        return c.getTimeInMillis()
    }

    //https://www.wolframalpha.com/input/?i=convert+1582-10-15+UTC+to+unix+time
    final static long START_OF_UUID_RELATIVE_TO_UNIX_EPOCH_SECONDS = -12219292800L
    final static long START_OF_UUID_RELATIVE_TO_UNIX_EPOCH_MILLIS = -12219292800L * 1000L

    /**
     * timestamp() from UUID is measured in 100-nanosecond units since midnight, October 15, 1582 UTC,
     * so we must convert for 100ns units to millisecond procession
     * @param tuid
     * @return
     */
    static long getMillisecondsFromUuid (UUID tuid) {

        assert tuid.version() == 1      //ensure its a time based UUID

        // timestamp returns in 10^-7 (100 nano second chunks), 
        // java Date constructor  assumes 10^-3 (millisecond precision)
        // so we have to divide by 10^4 (10,000) to get millisecond precision  
        long milliseconds_since_UUID_baseline = tuid.timestamp() /10000L

    }

    static getDateFromUuid (UUID tuid) {
        // Allocates a Date object and initializes it to represent the specified number of milliseconds since the 
        // standard java (unix) base time known as "the epoch", namely January 1, 1970, 00:00:00 GMT
        // have to add relative offset from UUID start date of unix epoch to get start date in unix time milliseconds 
        new Date (getMillisecondsFromUuid (tuid) + START_OF_UUID_RELATIVE_TO_UNIX_EPOCH_MILLIS )
    }

    static UUID getTimeBasedUuid () {
        UUID tuid = timeBasedGenerator.generate()
    }

}

我添加了解释性注释,以便您可以按照您必须执行的操作将 UUID timestamp() 方法处理为适用于正常 Java 日期和时间处理的格式。

为什么 Java UUID 类不能提供人们可能期望的方法来使基于时间的 UUID 与基于普通 unix 纪元的普通 java 日期/时间格式互操作,这对我来说是一个谜。

我使用上述静态方法运行了一个小测试脚本:

println "get start of epoch in milliseconds " + UuidUtil.getStartOfUuidRelativeToUnixEpochInMilliseconds()
assert UuidUtil.START_OF_UUID_RELATIVE_TO_UNIX_EPOCH_MILLIS == UuidUtil.startOfUuidRelativeToUnixEpochInMilliseconds

UUID tuid = UuidUtil.timeBasedUuid

println "uid : $tuid"

Date date = UuidUtil.getDateFromUuid(tuid)
println "extracted date from uid is " + UuidUtil.getDateFromUuid(tuid)

得到了这个

get start of epoch in milliseconds -12219292800000
uid : 43acb588-7d39-11e8-b37b-59f77bf2d333
extracted date from uid is Sun Jul 01 15:15:53 BST 2018

脚本运行的时间看起来是正确的。

【讨论】:

    【解决方案2】:

    要获得java.util.Instant 的完整 100ns 精度,您可以执行以下操作:

    private static final long NUM_HUNDRED_NANOS_IN_A_SECOND = 10_000_000L;
    
    private static final long NUM_HUNDRED_NANOS_FROM_UUID_EPOCH_TO_UNIX_EPOCH = 122_192_928_000_000_000L;
    
    
    /**
     * Extracts the Instant (with the maximum available 100ns precision) from the given time-based (version 1) UUID.
     *
     * @return the {@link Instant} extracted from the given time-based UUID
     * @throws UnsupportedOperationException If this UUID is not a version 1 UUID
     */
    public static Instant getInstantFromUUID(final UUID uuid) {
        final long hundredNanosSinceUnixEpoch = uuid.timestamp() - NUM_HUNDRED_NANOS_FROM_UUID_EPOCH_TO_UNIX_EPOCH;
        final long secondsSinceUnixEpoch = hundredNanosSinceUnixEpoch / NUM_HUNDRED_NANOS_IN_A_SECOND;
        final long nanoAdjustment = ((hundredNanosSinceUnixEpoch % NUM_HUNDRED_NANOS_IN_A_SECOND) * 100);
        return Instant.ofEpochSecond(secondsSinceUnixEpoch, nanoAdjustment);
    }
    

    【讨论】:

      【解决方案3】:

      “uuid-creator”库有一个实用程序类,可帮助提取 UUID 部分,如时间和节点 ID。看这个例子:

      long milliseconds = UuidUtil.extractUnixMilliseconds(uuid);
      

      项目: https://github.com/f4b6a3/uuid-creator

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-10-15
        • 2013-12-09
        • 1970-01-01
        • 1970-01-01
        • 2020-06-02
        • 2012-01-12
        相关资源
        最近更新 更多