1 /// Provides a wrapper for a `mg_duration`. Uses `core.time.Duration` internally. 2 module memgraph.duration; 3 4 import memgraph.mgclient, memgraph.detail, memgraph.value, memgraph.enums; 5 6 import ct = core.time; 7 8 /// Represents a temporal amount which captures the difference in time 9 /// between two instants. 10 /// Duration is defined with months, days, seconds, and nanoseconds. 11 /// Note: Duration can be negative. 12 /// Uses a `core.time.Duration` internally. 13 struct Duration { 14 /// Create a shallow copy of `other` Duration. 15 @nogc this(inout ref Duration other) { 16 this(other.ptr); 17 } 18 19 /// Create a duration from a Value. 20 @nogc this(inout ref Value value) { 21 assert(value.type == Type.Duration); 22 this(mg_value_duration(value.ptr)); 23 } 24 25 /// Return a printable string representation of this duration. 26 string toString() const { return duration_.toString; } 27 28 /// Returns the months part of the temporal amount. 29 @nogc auto months() const { return 0; } // See note in ctor. 30 31 /// Returns the days part of the temporal amount. 32 @nogc auto days() const { return duration_.total!"days"; } 33 34 /// Returns the seconds part of the temporal amount. 35 @nogc auto seconds() const { return (duration_ - ct.days(duration_.total!"days")).total!"seconds"; } 36 37 /// Returns the nanoseconds part of the temporal amount. 38 @nogc auto nanoseconds() const { return (duration_ - ct.seconds(duration_.total!"seconds")).total!"nsecs"; } 39 40 package: 41 /// Create a Duration using the given `mg_duration`. 42 @nogc this(const mg_duration *ptr) { 43 assert(ptr != null); 44 ptr_ = ptr; 45 // Note: there is no "months" duration in core.time because months have variable number of days 46 assert(mg_duration_months(ptr) == 0); 47 duration_ = ct.days(mg_duration_days(ptr)) + 48 ct.seconds(mg_duration_seconds(ptr)) + 49 ct.nsecs(mg_duration_nanoseconds(ptr)); 50 } 51 52 /// Return pointer to internal `mg_duration`. 53 @nogc auto ptr() inout { 54 return ptr_; 55 } 56 57 private: 58 const mg_duration *ptr_; 59 ct.Duration duration_; 60 alias duration_ this; 61 } // struct Duration 62 63 unittest { 64 import testutils : connectContainer; 65 import std.algorithm : count; 66 import std.conv : to; 67 68 auto client = connectContainer(); 69 assert(client); 70 71 auto result = client.execute(`return duration('P9DT11H23M7S');`); 72 assert(result, client.error); 73 foreach (r; result) { 74 assert(r.length == 1); 75 assert(r[0].type() == Type.Duration); 76 const d = to!Duration(r[0]); 77 assert(d.toString == "1 week, 2 days, 11 hours, 23 minutes, and 7 secs", d.toString); 78 assert(d.months == 0); 79 assert(d.days == 9); 80 assert(d.seconds == 11*60*60+23*60+7); 81 assert(d.nanoseconds == 0); 82 } 83 } 84 85 unittest { 86 import std.conv : to; 87 import memgraph.enums; 88 89 auto du = mg_duration_make(0, 5, 42, 230_000); 90 assert(du != null); 91 92 auto d = Duration(du); 93 assert(d.months == 0); 94 assert(d.days == 5); 95 assert(d.seconds == 42); 96 assert(d.nanoseconds == 230_000); 97 98 const d1 = d; 99 assert(d1 == d); 100 101 assert(to!string(d) == "5 days, 42 secs, and 230 μs", to!string(d)); 102 assert(d.toString == "5 days, 42 secs, and 230 μs", to!string(d)); 103 104 const ct.Duration dur = d; 105 assert(dur.toString == "5 days, 42 secs, and 230 μs", to!string(d)); 106 107 auto v = Value(mg_value_make_duration(du)); 108 assert(to!string(v) == "5 days, 42 secs, and 230 μs", to!string(v)); 109 }