1 /// Provides a wrapper around a `mg_local_time`. Uses `std.datetime.systime.SysTime` internally.
2 module memgraph.local_time;
3 
4 import memgraph.mgclient, memgraph.detail, memgraph.value, memgraph.enums;
5 import st = std.datetime.systime;
6 import sd = std.datetime.date;
7 import ct = core.time;
8 
9 /// Represents a local time.
10 /// Time is defined with nanoseconds since midnight.
11 struct LocalTime {
12   /// Create a shallow copy of `other` LocalTime.
13   this(inout ref LocalTime other) {
14     this(other.ptr);
15   }
16 
17   /// Create a local time from a Value.
18   this(inout ref Value value) {
19     assert(value.type == Type.LocalTime);
20     this(mg_value_local_time(value.ptr));
21   }
22 
23   /// Compares this local time with `other`.
24   /// Return: true if same, false otherwise.
25   @nogc auto opEquals(const ref LocalTime other) const {
26     return Detail.areLocalTimesEqual(ptr_, other.ptr_);
27   }
28 
29   /// Return a printable string representation of this local time.
30   string toString() const {
31     import std.format;
32     return format!("%02d:%02d:%02d.%09d")(localTime_.hour, localTime_.minute, localTime_.second,
33                   localTime_.fracSecs.total!"nsecs");
34   }
35 
36   /// Return the hash code for this local time.
37   size_t toHash() const nothrow @safe {
38     return cast(ulong)ptr_;
39   }
40 
41   /// Returns nanoseconds since midnight.
42   @nogc auto nanoseconds() const { return nanoSeconds_; }
43 
44 package:
45   /// Create a LocalTime using the given `mg_local_time` pointer.
46   this(inout mg_local_time *ptr) {
47     assert(ptr != null);
48     ptr_ = ptr;
49     nanoSeconds_ = mg_local_time_nanoseconds(ptr);
50     immutable auto now = st.Clock.currTime();
51     localTime_ = st.SysTime(sd.DateTime(now.year, now.month, now.day, 0, 0, 0));
52     localTime_ += ct.nsecs(nanoSeconds_);
53   }
54 
55   /// Returns the internal `mg_local_time` pointer.
56   @nogc auto ptr() inout {
57     return ptr_;
58   }
59 
60 private:
61   const mg_local_time *ptr_;
62   st.SysTime localTime_;
63   long nanoSeconds_;
64   alias localTime_ this;
65 } // struct LocalTime
66 
67 unittest {
68   import testutils : connectContainer;
69   import std.conv : to;
70 
71   auto client = connectContainer();
72   assert(client);
73 
74   auto result = client.execute(`return localtime('12:34:56.100');`);
75   assert(result, client.error);
76   foreach (r; result) {
77     assert(r.length == 1);
78     assert(r[0].type() == Type.LocalTime);
79     const t = to!LocalTime(r[0]);
80     assert(t.toString == "12:34:56.100000000", t.toString);
81     assert(t.nanoseconds == 45_296_100_000_000);
82   }
83 }
84 
85 unittest {
86   import std.conv : to;
87 
88   auto tm = mg_local_time_make(45_296_100_000_000);
89   assert(tm != null);
90 
91   auto t = LocalTime(tm);
92   assert(t.nanoseconds == 45_296_100_000_000);
93 
94   const t1 = t;
95   assert(t1 == t);
96 
97   assert(to!string(t) == "12:34:56.100000000");
98   assert(t.toString == "12:34:56.100000000");
99 
100   st.SysTime st = t;
101   import std.format;
102   assert(format!("%02d:%02d:%02d.%09d")(st.hour, st.minute, st.second,
103                 st.fracSecs.total!"nsecs") == t.toString);
104 
105   auto t2 = LocalTime(t.ptr);
106   assert(t2 == t);
107 
108   const t3 = LocalTime(t2);
109   assert(t3 == t);
110 
111   const t5 = LocalTime(t3);
112   assert(t5 == t3);
113 
114   auto v = Value(mg_value_make_local_time(tm));
115   assert(to!string(v) == "12:34:56.100000000", to!string(v));
116 
117   assert(cast(ulong)t.ptr == t.toHash);
118 }