获取基于时间的uuid,最长可达100纳秒

eoxn13cs  于 2021-06-10  发布在  Cassandra
关注(0)|答案(1)|浏览(431)

我在用这个 libraryDependencies += "com.datastax.oss" % "java-driver-core" % "4.3.0" 用于创建基于时间的uuid的库。虽然它生成基于时间的uuid,它给我最多秒,但我在寻找100纳秒的值

import com.datastax.oss.driver.api.core.uuid.Uuids
println(Uuids.timeBased().toString)

输出uuid类似于 f642f350-0230-11ea-a02f-597f2801796a 对应于 Friday, November 8, 2019 at 2:06:30 PM Greenwich Mean Time 请帮助我们如何用毫秒来计算这样的时间 Friday, November 8, 2019 at 2:06:30:0000000Z PM Greenwich Mean Time 我希望时间戳转换成uuid格式进行测试(测试只接受uuid格式)。然后我将uuid转换回时间来测量时间差。

clj7thdc

clj7thdc1#

这里有几个步骤。第一种方法是将基于时间的uuid的时间戳(从1582年10月15日起为100纳秒)转换为与java的日期功能兼容的时间戳(即从1970年1月1日起为毫秒)。值得注意的是,您要求的精度高于毫秒。
接下来,我们需要将该日期解释为正确的时区。
最后,我们需要将其格式化为所需格式的文本。
代码如下:

// this is the difference between midnight October 15, 1582 UTC and midnight January 1, 1970 UTC as 100 nanosecond units
private static final long EPOCH_DIFFERENCE = 122192928000000000L;

private static final ZoneId GREENWICH_MEAN_TIME = ZoneId.of("GMT");

private static final DateTimeFormatter FORMATTER = new DateTimeFormatterBuilder()
        .appendText(DAY_OF_WEEK, FULL)
        .appendLiteral(", ")
        .appendText(MONTH_OF_YEAR, FULL)
        .appendLiteral(' ')
        .appendValue(DAY_OF_MONTH)
        .appendLiteral(", ")
        .appendValue(YEAR, 4)
        .appendLiteral(" at ")
        .appendValue(CLOCK_HOUR_OF_AMPM)
        .appendLiteral(':')
        .appendValue(MINUTE_OF_HOUR, 2)
        .appendLiteral(':')
        .appendValue(SECOND_OF_MINUTE, 2)
        .appendLiteral('.')
        .appendFraction(NANO_OF_SECOND, 7, 7, false)
        .appendLiteral(' ')
        .appendText(AMPM_OF_DAY)
        .appendLiteral(' ')
        .appendZoneText(FULL)
        .toFormatter(Locale.getDefault());

public static String formattedDateFromTimeBasedUuid(UUID uuid) {
    ZonedDateTime date = timeBasedUuidToDate(uuid);
    return FORMATTER.format(date);
}

public static ZonedDateTime timeBasedUuidToDate(UUID uuid) {
    if (uuid.version() != 1) {
        throw new IllegalArgumentException("Provided UUID was not time-based.");
    }
    // the UUID timestamp is in 100 nanosecond units.
    // convert that to nanoseconds
    long nanoseconds = (uuid.timestamp() - EPOCH_DIFFERENCE) * 100;
    long milliseconds = nanoseconds / 1000000000;
    long nanoAdjustment = nanoseconds % 1000000000;
    Instant instant = Instant.ofEpochSecond(milliseconds, nanoAdjustment);
    return ZonedDateTime.ofInstant(instant, GREENWICH_MEAN_TIME);
}

为了便于重用,我会将这些方法和常量放到实用程序类中。
几个注意事项:
这里有很多静态导入的常量。它们来自 java.time.format.TextStyle 以及 java.time.temporal.ChronoField .
我曾经 DateTimeFormatterBuilder 而不是更常见的 DateTimeFormatter.forPattern(String) . 我觉得它更具可读性,并愿意容忍由此产生的冗长。
我对你想要的格式做了一个调整:你要求的是时间 2:06:30:001 ; 此代码生成 2:06:30.001 --秒和毫秒之间的小数点,而不是冒号。这是更正确的,但如果你喜欢冒号,只要改变相应的 .appendLiteral('.') 而是通过一个冒号。
您经常可以找到内联定义datetimeformatters、zoneids等的示例代码。这些类是线程安全的和可重用的,因此为了获得最佳结果,应该将它们定义为常量,就像我在这里所做的那样。您将获得更好的性能并减少内存使用。
请注意,税务驱动程序 Uuids 类使用系统时钟的毫秒精度值作为输入,所以在最后四个位置只会看到零,除非实现自己的基于纳秒的变体。你可以用 System.nanoTime() ,但也有一些复杂的地方--请查看javadoc上的注解以了解更多信息。
要确定两个ZoneDateTimes之间的时间量,只需执行以下操作:

Duration duration = Duration.between(date1, date2);

这个 Duration 类有几个有用的方法可以用来解释结果。

相关问题