Как я могу получить дату / время обратно из UUID типа 1
Я включил следующую группу компиляции библиотеки UUID: 'com.fasterxml.uuid', имя: 'java-uuid-generator', версия: '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())
однако, когда я пытаюсь взглянуть на дату, она не похожа на ту, что должна быть, например, я получаю 'uid fef57eca-7c8b-11e8-bedd-992c2ac3197a было вс 6 февраля 07:55:54 GMT 6327', когда сегодня 30/06/2018
Кто-нибудь знает, как правильно извлечь реальную дату и время из UUID, основанного на времени, используя библиотеку fastxml.uuid?
но в тупик
PS попробовал это вместо
UUID tuid = timeBasedGenerator.generate()
Long t = tuid.timestamp()
Timestamp timestamp = new Timestamp (t)
Date dateTime = new Date (timestamp.getTime())
который дает идентификатор ff79d7d9-7cb5-11e8-976c-6ba57a5e9636 и дату Чт 14 августа 11:11:40 BST 4359073
3 ответа
Чтобы получить полную точность 100 нс в качестве
java.util.Instant
, вы можете сделать следующее:
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);
}
Хорошо, после не очень полезных комментариев, я сделал еще немного grubbing в Google и т. д.
построил следующий класс "простая утилита", который может быть расширен по мере необходимости
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 на основе времени, совместимым с обычными форматами даты / времени Java, основанными на обычной эпохе Unix, для меня загадка -
запустил небольшой тестовый скрипт, используя вышеописанные статические методы
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
который выглядел правильно для времени запуска сценария
В библиотеке uuid-creator есть служебный класс, который помогает извлекать части UUID, такие как время и идентификатор узла. См. Этот пример:
long milliseconds = UuidUtil.extractUnixMilliseconds(uuid);