获得基于时间的uuid高达100纳秒

我正在使用这个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,2019 at 2:06:30:0000000Z PM Greenwich Mean Time

我希望将时间戳转换为uuid格式进行测试(测试仅接受uuid格式)。然后,我会将uuid转换回时间以测量一些时差。

hlplyz 回答:获得基于时间的uuid高达100纳秒

这里有几个步骤。第一种是将基于时间的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,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.TextStylejava.time.temporal.ChronoField
  • 我使用了DateTimeFormatterBuilder而不是更常见的DateTimeFormatter.forPattern(String)。我发现它更具可读性,并愿意容忍由此产生的冗长。
  • 我对您想要的格式做了一件事:您要求时间为2:06:30:001;这段代码产生2:06:30.001 -在秒和毫秒之间的小数点,而不是冒号。这是更正确的方法,但是如果您更喜欢冒号,只需更改相应的.appendLiteral('.')即可通过冒号。
  • 您经常会找到示例代码,它们内联定义了DateTimeFormatters,ZoneIds等。这些类是线程安全的和可重用的,因此为了获得最佳结果,您应该像在此所做的那样将它们定义为常量。您将获得更好的性能并减少内存使用。
  • 请注意,DataStax驱动程序的Uuids类使用系统时钟的毫秒精度值作为输入,因此除非您实现自己的基于纳秒的变量,否则您只会在最后四个位置看到零。您可以使用System.nanoTime()来做到这一点,但有一些麻烦-check out the note on the JavaDoc for more

要确定两个ZonedDateTime之间的时间量,只需执行以下操作:

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

Duration类具有several useful methods,可用于解释结果。

本文链接:https://www.f2er.com/3137233.html

大家都在问