簡體   English   中英

獲取基於時間的 uuid 最多 100 納秒

[英]get timebased uuid's upto 100s of nanoseconds

我正在使用這個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)

output 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 轉換回時間以測量一些時間差。

這里有幾個步驟。 第一個是將基於時間的 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);
}

為了方便重用,我會將這些方法和常量放在實用程序 class 中。

幾點注意事項:

  • 這里有很多靜態導入的常量。 它們來自java.time.format.TextStylejava.time.temporal.ChronoField
  • 我使用DateTimeFormatterBuilder而不是更常見的DateTimeFormatter.forPattern(String) 我發現它更具可讀性,並且願意容忍由此產生的冗長。
  • 我調整了您想要的格式的一件事:您要求時間為2:06:30:001 此代碼產生2:06:30.001 - 秒和毫秒之間的小數點,而不是冒號。 這更正確,但如果您更喜歡冒號,只需將相應的.appendLiteral('.')更改為傳遞冒號即可。
  • 您經常會發現內聯定義 DateTimeFormatters、ZoneIds 等的示例代碼。 這些類是線程安全且可重用的,因此為了獲得最佳結果,您應該將它們定義為常量,就像我在這里所做的那樣。 您將獲得更好的性能並減少 memory 的使用。
  • 請注意,DataStax 驅動程序的Uuids class 使用系統時鍾的毫秒精度值作為輸入,因此您只會在最后四個位置看到零,除非您實現自己的基於納秒的變體。 您可以使用System.nanoTime()來做到這一點,但有一些復雜性—— 請查看 JavaDoc 上的注釋了解更多信息

要確定兩個 ZonedDateTimes 之間的時間量,您只需執行以下操作:

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

Duration class 有幾種有用的方法可以用來解釋結果。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM