Initialize the monotonic factory with the minimum timestamp
Now the `MonotonicFunction` inner class is initialized with the instant 1970-01-01 00:00:00.000 UTC, which is represented by the value 0L. Also updated the documentation and the unit tests.
This commit is contained in:
parent
c7191c6e27
commit
dbf31d3be7
|
@ -149,10 +149,14 @@ public final class Ulid implements Serializable, Comparable<Ulid> {
|
||||||
/**
|
/**
|
||||||
* Creates a new ULID.
|
* Creates a new ULID.
|
||||||
* <p>
|
* <p>
|
||||||
* Time parameter is the number of milliseconds since 1970-01-01 (Unix epoch).
|
* The time parameter is the number of milliseconds since 1970-01-01, also known
|
||||||
* It must be a positive number not larger than 2^48-1.
|
* as Unix epoch. It must be a positive number not larger than 2^48-1.
|
||||||
* <p>
|
* <p>
|
||||||
* Random parameter must be an array of 10 bytes.
|
* The random parameter must be an arbitrary array of 10 bytes.
|
||||||
|
* <p>
|
||||||
|
* Note: ULIDs cannot be composed of dates before 1970-01-01, as their embedded
|
||||||
|
* timestamp is internally treated as an unsigned integer, i.e., it can only
|
||||||
|
* represent the set of natural numbers including zero, up to 2^48-1.
|
||||||
*
|
*
|
||||||
* @param time the number of milliseconds since 1970-01-01
|
* @param time the number of milliseconds since 1970-01-01
|
||||||
* @param random an array of 10 bytes
|
* @param random an array of 10 bytes
|
||||||
|
|
|
@ -360,7 +360,8 @@ public final class UlidFactory {
|
||||||
}
|
}
|
||||||
|
|
||||||
void initialize(LongSupplier timeFunction) {
|
void initialize(LongSupplier timeFunction) {
|
||||||
this.lastUlid = new Ulid(timeFunction.getAsLong(), this.random.nextBytes(Ulid.RANDOM_BYTES));
|
// initialize the factory with the instant 1970-01-01 00:00:00.000 UTC
|
||||||
|
this.lastUlid = new Ulid(0L, this.random.nextBytes(Ulid.RANDOM_BYTES));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -39,8 +39,7 @@ public class UlidFactoryMonotonicTest extends UlidFactoryTest {
|
||||||
|
|
||||||
long diff = UlidFactory.MonotonicFunction.CLOCK_DRIFT_TOLERANCE;
|
long diff = UlidFactory.MonotonicFunction.CLOCK_DRIFT_TOLERANCE;
|
||||||
long time = Instant.parse("2021-12-31T23:59:59.000Z").toEpochMilli();
|
long time = Instant.parse("2021-12-31T23:59:59.000Z").toEpochMilli();
|
||||||
long times[] = { /* init */ 0L, time + 0, time + 1, time + 2, time + 3, time + 4 - diff, time + 5 - diff,
|
long times[] = { time + 0, time + 1, time + 2, time + 3, time + 4 - diff, time + 5 - diff, time + 6 - diff };
|
||||||
time + 6 - diff };
|
|
||||||
|
|
||||||
Clock clock = new Clock() {
|
Clock clock = new Clock() {
|
||||||
private int i;
|
private int i;
|
||||||
|
@ -113,8 +112,11 @@ public class UlidFactoryMonotonicTest extends UlidFactoryTest {
|
||||||
@Test
|
@Test
|
||||||
public void testGetMonotonicUlidAfterLeapSecond() {
|
public void testGetMonotonicUlidAfterLeapSecond() {
|
||||||
|
|
||||||
|
// The best article about leap seconds:
|
||||||
|
// (Unfortunately it can't be translated)
|
||||||
|
// https://ntp.br/conteudo/artigo-leap-second/
|
||||||
long time = Instant.parse("2021-12-31T23:59:59.000Z").toEpochMilli();
|
long time = Instant.parse("2021-12-31T23:59:59.000Z").toEpochMilli();
|
||||||
long leap = time - 1000; // simulate a leap second
|
long leap = time - 1000; // moving the clock hands 1 second backwards
|
||||||
long times[] = { time, leap };
|
long times[] = { time, leap };
|
||||||
|
|
||||||
Clock clock = new Clock() {
|
Clock clock = new Clock() {
|
||||||
|
@ -144,28 +146,26 @@ public class UlidFactoryMonotonicTest extends UlidFactoryTest {
|
||||||
LongSupplier randomFunction = () -> 0;
|
LongSupplier randomFunction = () -> 0;
|
||||||
UlidFactory factory = UlidFactory.newMonotonicInstance(randomFunction, clock);
|
UlidFactory factory = UlidFactory.newMonotonicInstance(randomFunction, clock);
|
||||||
|
|
||||||
|
// the clock moved normally
|
||||||
Ulid ulid1 = factory.create();
|
Ulid ulid1 = factory.create();
|
||||||
Ulid ulid2 = factory.create();
|
|
||||||
|
|
||||||
long t1 = ulid1.getTime();
|
long t1 = ulid1.getTime();
|
||||||
long t2 = ulid2.getTime(); // leap second
|
|
||||||
|
|
||||||
long r1 = ulid1.getLeastSignificantBits();
|
long r1 = ulid1.getLeastSignificantBits();
|
||||||
long r2 = ulid2.getLeastSignificantBits(); // leap second
|
|
||||||
|
|
||||||
assertEquals(time, t1);
|
assertEquals(time, t1);
|
||||||
assertEquals(time, t2); // leap second
|
assertEquals(0, r1);
|
||||||
|
|
||||||
assertEquals(1, r1);
|
|
||||||
assertEquals(2, r2);
|
|
||||||
|
|
||||||
|
// the clock moved backwards
|
||||||
|
Ulid ulid2 = factory.create();
|
||||||
|
long t2 = ulid2.getTime();
|
||||||
|
long r2 = ulid2.getLeastSignificantBits();
|
||||||
|
assertEquals(time, t2); // should freeze
|
||||||
|
assertEquals(1, r2); // should increment
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetMonotonicUlidAfterRandomBitsOverflowFollowedByTimeBitsIncrement() {
|
public void testGetMonotonicUlidAfterRandomBitsOverflowFollowedByTimeBitsIncrement() {
|
||||||
|
|
||||||
long time = Instant.parse("2021-12-31T23:59:59.999Z").toEpochMilli();
|
long time = Instant.parse("2021-12-31T23:59:59.999Z").toEpochMilli();
|
||||||
long times[] = { /* init */ 0L, time + 1, time + 2, time + 3, time, time, time };
|
long times[] = { time + 1, time + 2, time + 3, time, time, time };
|
||||||
|
|
||||||
Clock clock = new Clock() {
|
Clock clock = new Clock() {
|
||||||
private int i;
|
private int i;
|
||||||
|
@ -194,8 +194,6 @@ public class UlidFactoryMonotonicTest extends UlidFactoryTest {
|
||||||
LongSupplier randomSupplier = () -> 0xffffffffffffffffL;
|
LongSupplier randomSupplier = () -> 0xffffffffffffffffL;
|
||||||
UlidFactory factory = UlidFactory.newMonotonicInstance(randomSupplier, clock);
|
UlidFactory factory = UlidFactory.newMonotonicInstance(randomSupplier, clock);
|
||||||
|
|
||||||
// System.out.println("time: " + time); // 1640995199999
|
|
||||||
|
|
||||||
Ulid ulid1 = factory.create();
|
Ulid ulid1 = factory.create();
|
||||||
Ulid ulid2 = factory.create();
|
Ulid ulid2 = factory.create();
|
||||||
Ulid ulid3 = factory.create();
|
Ulid ulid3 = factory.create();
|
||||||
|
|
Loading…
Reference in New Issue