]> git.argeo.org Git - lgpl/argeo-commons.git/blobdiff - org.argeo.api.uuid/src/org/argeo/api/uuid/TimeUuid.java
Introduce typed UUIDs.
[lgpl/argeo-commons.git] / org.argeo.api.uuid / src / org / argeo / api / uuid / TimeUuid.java
diff --git a/org.argeo.api.uuid/src/org/argeo/api/uuid/TimeUuid.java b/org.argeo.api.uuid/src/org/argeo/api/uuid/TimeUuid.java
new file mode 100644 (file)
index 0000000..2f3a73f
--- /dev/null
@@ -0,0 +1,78 @@
+package org.argeo.api.uuid;
+
+import java.time.Duration;
+import java.time.Instant;
+import java.time.ZoneOffset;
+import java.time.ZonedDateTime;
+import java.util.UUID;
+
+/**
+ * A time based UUID, whose content can therefore be usefully interpreted as
+ * time and node identifier information.
+ */
+public class TimeUuid extends TypedUuid {
+       private static final long serialVersionUID = APM.SERIAL;
+       /**
+        * Start of the Gregorian time on October 15th 1582, equivalent to
+        * <code>{@link UUID#timestamp()} == 0</code>.
+        */
+       public final static Instant TIMESTAMP_ZERO = ZonedDateTime.of(1582, 10, 15, 0, 0, 0, 0, ZoneOffset.UTC).toInstant();
+
+       public TimeUuid(UUID uuid) {
+               super(uuid);
+               if (uuid.version() != 1 && uuid.variant() != 2)
+                       throw new IllegalArgumentException("The provided UUID is not a time based UUID.");
+       }
+
+       /** {@link UUID#timestamp()} as an {@link Instant}. */
+       public final Instant getInstant() {
+               long timestamp = uuid.timestamp();
+               return TIMESTAMP_ZERO.plus(timestampDifferenceToDuration(timestamp));
+       }
+
+       /** {@link UUID#node()} as an hex string. */
+       public final String getNodeId() {
+               return Long.toHexString(uuid.node());
+       }
+
+       /** {@link UUID#clockSequence()} as an hex string. */
+       public final String getClockSequence() {
+               return Long.toHexString(uuid.clockSequence());
+       }
+
+       /**
+        * Always returns <code>false</code> since time UUIDs are by definition not
+        * opaque.
+        */
+       @Override
+       public final boolean isOpaque() {
+               return false;
+       }
+
+       /*
+        * STATIC UTILITIES
+        */
+       /** Converts from duration in the time UUID timestamp format. */
+       public static Duration timestampDifferenceToDuration(long timestampDifference) {
+               long seconds = timestampDifference / 10000000;
+               long nano = (timestampDifference % 10000000) * 100;
+               return Duration.ofSeconds(seconds, nano);
+       }
+
+       /**
+        * A duration expressed in the time UUID timestamp format based on units of 100
+        * ns.
+        */
+       public static long durationToTimestamp(Duration duration) {
+               return (duration.getSeconds() * 10000000 + duration.getNano() / 100);
+       }
+
+       /**
+        * An instant expressed in the time UUID timestamp format based on units of 100
+        * ns since {@link #TIMESTAMP_ZERO}.
+        */
+       public static long instantToTimestamp(Instant instant) {
+               Duration duration = Duration.between(TimeUuid.TIMESTAMP_ZERO, instant);
+               return durationToTimestamp(duration);
+       }
+}