Skip to content

Commit 4e1249c

Browse files
committed
UUIDv7: ctor accepts MonoTime as recommentded by IETF
1 parent 491e4cc commit 4e1249c

File tree

1 file changed

+52
-14
lines changed

1 file changed

+52
-14
lines changed

std/uuid.d

Lines changed: 52 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ module std.uuid;
120120
assert(id.empty);
121121
}
122122

123-
import core.time : dur;
123+
import core.time : dur, MonoTimeImpl;
124124
import std.datetime.systime : SysTime;
125125
import std.datetime : Clock, DateTime, UTC;
126126
import std.range.primitives;
@@ -323,21 +323,37 @@ public struct UUID
323323
* random = UUID V7 has 74 bits of random data, which rounds to 10 ubyte's.
324324
* If no random data is given, random data is generated.
325325
*/
326+
@safe pure this(TMonoTime)(TMonoTime timestamp, ubyte[10] random = generateV7RandomData())
327+
if(isInstanceOf!(MonoTimeImpl, TMonoTime))
328+
{
329+
import std.datetime;
330+
331+
TMonoTime epochStart = TMonoTime.zero + unixTimeToStdTime(0).seconds;
332+
ulong epoch = (timestamp - epochStart).total!"msecs";
333+
this(epoch, random);
334+
}
335+
336+
/// ditto
326337
@safe pure this(SysTime timestamp, ubyte[10] random = generateV7RandomData())
327338
{
328339
ulong epoch = (timestamp - SysTime.fromUnixTime(0)).total!"msecs";
329-
this.data[6 .. $] = random[];
340+
this(epoch, random);
341+
}
330342

331-
this.data[0] = cast(ubyte)((epoch >> 40) & 0xFF);
332-
this.data[1] = cast(ubyte)((epoch >> 32) & 0xFF);
333-
this.data[2] = cast(ubyte)((epoch >> 24) & 0xFF);
334-
this.data[3] = cast(ubyte)((epoch >> 16) & 0xFF);
335-
this.data[4] = cast(ubyte)((epoch >> 8) & 0xFF);
336-
this.data[5] = cast(ubyte)(epoch & 0xFF);
343+
///
344+
@system unittest
345+
{
346+
import core.time : Duration;
347+
import std.datetime;
337348

338-
// version and variant
339-
this.data[6] = (this.data[6] & 0x0F) | 0x70;
340-
this.data[8] = (this.data[8] & 0x3F) | 0x80;
349+
MonoTime mt = MonoTime.currTime;
350+
MonoTime mt_epoch_start = MonoTime.zero + unixTimeToStdTime(0).seconds;
351+
Duration mt_dur = mt - mt_epoch_start;
352+
353+
UUID u = UUID(mt);
354+
Duration u_dur = u.v7Milliseconds().msecs;
355+
356+
assert(u_dur == mt_dur, mt.toString() ~ " | " ~ u.toString());
341357
}
342358

343359
///
@@ -350,6 +366,22 @@ public struct UUID
350366
assert(o == st, st.toString() ~ " | " ~ o.toString());
351367
}
352368

369+
private @safe pure this(long epoch, ubyte[10] random)
370+
{
371+
this.data[6 .. $] = random[];
372+
373+
this.data[0] = cast(ubyte)((epoch >> 40) & 0xFF);
374+
this.data[1] = cast(ubyte)((epoch >> 32) & 0xFF);
375+
this.data[2] = cast(ubyte)((epoch >> 24) & 0xFF);
376+
this.data[3] = cast(ubyte)((epoch >> 16) & 0xFF);
377+
this.data[4] = cast(ubyte)((epoch >> 8) & 0xFF);
378+
this.data[5] = cast(ubyte)(epoch & 0xFF);
379+
380+
// version and variant
381+
this.data[6] = (this.data[6] & 0x0F) | 0x70;
382+
this.data[8] = (this.data[8] & 0x3F) | 0x80;
383+
}
384+
353385
/**
354386
* <a name="UUID(string)"></a>
355387
* Parse a UUID from its canonical string form. An UUID in its
@@ -561,18 +593,23 @@ public struct UUID
561593
* returns, otherwise and UUIDParsingException is thrown.
562594
*/
563595
SysTime v7Timestamp() const {
596+
return SysTime(DateTime(1970, 1, 1), UTC()) + dur!"msecs"(v7Milliseconds());
597+
}
598+
599+
/// ditto
600+
ulong v7Milliseconds() const {
564601
if (this.uuidVersion != Version.timestampRandom)
565602
{
566603
throw new UUIDParsingException("The UUID is not of version" ~
567604
" v7 therefore no timestamp exist", 0);
568605
}
569-
ulong milli = (cast(ulong)(this.data[0]) << 40) |
606+
607+
return (cast(ulong)(this.data[0]) << 40) |
570608
(cast(ulong)(this.data[1]) << 32) |
571609
(cast(ulong)(this.data[2]) << 24) |
572610
(cast(ulong)(this.data[3]) << 16) |
573611
(cast(ulong)(this.data[4]) << 8) |
574612
(cast(ulong)(this.data[5]));
575-
return SysTime(DateTime(1970, 1, 1), UTC()) + dur!"msecs"(milli);
576613
}
577614

578615
/**
@@ -1384,7 +1421,8 @@ if (isInputRange!RNG && isIntegral!(ElementType!RNG))
13841421
*/
13851422
UUID timestampRandomUUID()
13861423
{
1387-
return UUID(Clock.currTime());
1424+
import core.time : MonoTime;
1425+
return UUID(MonoTime.currTime);
13881426
}
13891427

13901428
///

0 commit comments

Comments
 (0)