I am using this libraryDependencies += "com.datastax.oss" % "java-driver-core" % "4.3.0"
library for creating time based uuid's. Although it generates time based uuid's it gives me upto seconds but i am looking for values in 100s of nano seconds
import com.datastax.oss.driver.api.core.uuid.Uuids
println(Uuids.timeBased().toString)
The output uuid is something like f642f350-0230-11ea-a02f-597f2801796a
which corresponds to
Friday, November 8, 2019 at 2:06:30 PM Greenwich Mean Time
Please help on how to get time in milliseconds seomething like this
Friday, November 8, 2019 at 2:06:30:0000000Z PM Greenwich Mean Time
I want timestamp to be converted in uuid format for testing(tests accept only uuid format). i would then convert uuid back to time to measure some time difference.
There are a few steps here. The first is to convert the time-based UUID's timestamp (which is in 100s of nanoseconds from October 15, 1582) to one compatible with Java's date functionality (i.e. milliseconds from January 1, 1970). Notably, you asked for better than millisecond precision.
Next, we need to interpret that date into the correct time zone.
Finally, we need to format it into text in the desired format.
Here's the code:
// 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);
}
I'd drop those methods and constants in a utility class for convenient reuse.
A couple notes:
java.time.format.TextStyle
and java.time.temporal.ChronoField
.DateTimeFormatterBuilder
instead of the more common DateTimeFormatter.forPattern(String)
. I find it more readable and am willing to tolerate the resulting verbosity.2:06:30:001
; this code yields 2:06:30.001
-- a decimal point between the seconds and milliseconds, rather than a colon. This is more correct, but if you prefer the colon, just change the corresponding .appendLiteral('.')
to pass a colon instead.Uuids
class uses the system clock's millisecond-precision value as input, so you're just going to see zeros in the last four positions, unless you implement your own nanosecond-based variant. You could do that using System.nanoTime()
, but there are some complications -- check out the note on the JavaDoc for more.To determine the amount of time between two ZonedDateTimes, you just do this:
Duration duration = Duration.between(date1, date2);
The Duration
class has several useful methods you can use to interpret the result.