1 /// Provides a wrapper around a `mg_local_date_time`. Uses `std.datetime.systime.SysTime` internally.
2 module memgraph.local_date_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 date and time without its time zone.
10 /// Date is defined with seconds since the Unix epoch.
11 /// Time is defined with nanoseconds since midnight.
12 struct LocalDateTime {
13 
14   /// Create a shallow copy of `other` LocalDateTime.
15   this(inout ref LocalDateTime other) {
16     this(other.ptr);
17   }
18 
19   /// Create a local date time from a Value.
20   this(inout ref Value value) {
21     assert(value.type == Type.LocalDateTime);
22     this(mg_value_local_date_time(value.ptr));
23   }
24 
25   /// Return a printable string representation of this local date time.
26   string toString() const { return dateTime_.toString; }
27 
28   /// Returns seconds since Unix epoch.
29   @nogc auto seconds() const { return epoch_; }
30 
31   /// Returns nanoseconds since midnight.
32   @nogc auto nanoseconds() const { return nanos_; }
33 
34 package:
35   /// Create a LocalDateTime using the given `mg_local_date_time`.
36   this(const mg_local_date_time *ptr) {
37     assert(ptr != null);
38     ptr_ = ptr;
39     epoch_ = mg_local_date_time_seconds(ptr);
40     nanos_ = mg_local_date_time_nanoseconds(ptr);
41     dateTime_ = st.SysTime(st.unixTimeToStdTime(epoch_));
42     dateTime_ += ct.nsecs(nanos_);
43   }
44 
45   /// Return pointer to internal `mg_local_date_time`.
46   @nogc auto ptr() inout {
47     return ptr_;
48   }
49 
50 private:
51   const mg_local_date_time *ptr_;
52   long epoch_;
53   long nanos_;
54   st.SysTime dateTime_;
55   alias dateTime_ this;
56 } // struct LocalDateTime
57 
58 unittest {
59   import testutils : connectContainer;
60   import std.algorithm : count;
61   import std.conv : to;
62 
63   auto client = connectContainer();
64   assert(client);
65 
66   auto result = client.execute(`return localdatetime('2021-12-13T12:34:56.100');`);
67   assert(result, client.error);
68   foreach (r; result) {
69     assert(r.length == 1);
70     assert(r[0].type() == Type.LocalDateTime);
71     auto t = to!LocalDateTime(r[0]);
72     assert(t.toString == "2021-Dec-13 12:34:56.1", t.toString);
73     assert(t.toISOString == "20211213T123456.1", t.toISOString);
74     assert(t.toISOExtString == "2021-12-13T12:34:56.1", t.toISOExtString);
75     assert(t.seconds == 1_639_398_896, to!string(t.seconds));
76     assert(t.nanoseconds == 100_000_000, to!string(t.nanoseconds));
77   }
78 }
79 
80 unittest {
81   import std.conv : to;
82   import memgraph.enums;
83 
84   auto tm = mg_local_date_time_make(1_639_398_896, 100_000_000);
85   assert(tm != null);
86 
87   auto t = LocalDateTime(tm);
88   assert(t.seconds == 1_639_398_896);
89   assert(t.nanoseconds == 100_000_000);
90 
91   const t1 = t;
92   assert(t1 == t);
93 
94   assert(to!string(t) == "2021-Dec-13 12:34:56.1", to!string(t));
95 
96   st.SysTime st = t;
97   assert(to!string(st) == "2021-Dec-13 12:34:56.1", to!string(st));
98 
99   auto t2 = LocalDateTime(t.ptr);
100   assert(t2 == t);
101 
102   const t3 = LocalDateTime(t2);
103   assert(t3 == t);
104 
105   const t5 = LocalDateTime(t3);
106   assert(t5 == t3);
107 }