1 /// Provides a wrapper around a `mg_time`.
2 module memgraph.time;
3 
4 import memgraph.mgclient, memgraph.detail, memgraph.value, memgraph.enums;
5 
6 /// Represents time with its time zone.
7 ///
8 /// Time is defined with nanoseconds since midnight.
9 /// Timezone is defined with seconds from UTC.
10 struct Time {
11 	/// Create a copy of `other` time.
12 	this(inout ref Time other) {
13 		this(mg_time_copy(other.ptr));
14 	}
15 
16 	/// Create a time from a Value.
17 	this(inout ref Value value) {
18 		assert(value.type == Type.Time);
19 		this(mg_time_copy(mg_value_time(value.ptr)));
20 	}
21 
22 	/// Assigns a time to another. The target of the assignment gets detached from
23 	/// whatever time it was attached to, and attaches itself to the new time.
24 	ref Time opAssign(Time rhs) @safe return {
25 		import std.algorithm.mutation : swap;
26 		swap(this, rhs);
27 		return this;
28 	}
29 
30 	/// Return a printable string representation of this time.
31 	const (string) toString() const {
32 		import std.conv : to;
33 		return to!string(nanoseconds) ~ " " ~ to!string(tz_offset_seconds);
34 	}
35 
36 	/// Compares this time with `other`.
37 	/// Return: true if same, false otherwise.
38 	bool opEquals(const ref Time other) const {
39 		return Detail.areTimesEqual(ptr_, other.ptr);
40 	}
41 
42 	/// Returns nanoseconds since midnight.
43 	const (long) nanoseconds() const { return mg_time_nanoseconds(ptr_); }
44 
45 	/// Returns time zone offset in seconds from UTC.
46 	const (long) tz_offset_seconds() const { return mg_time_tz_offset_seconds(ptr_); }
47 
48 	this(this) {
49 		if (ptr_)
50 			ptr_ = mg_time_copy(ptr_);
51 	}
52 
53 	@safe @nogc ~this() {
54 		if (ptr_)
55 			mg_time_destroy(ptr_);
56 	}
57 
58 package:
59 	/// Create a Time using the given `mg_time`.
60 	this(mg_time *ptr) @trusted {
61 		assert(ptr != null);
62 		ptr_ = ptr;
63 	}
64 
65 	/// Create a Time from a copy of the given `mg_time`.
66 	this(const mg_time *ptr) {
67 		assert(ptr != null);
68 		this(mg_time_copy(ptr));
69 	}
70 
71 	const (mg_time *) ptr() const { return ptr_; }
72 
73 private:
74 	mg_time *ptr_;
75 }
76 
77 unittest {
78 	import std.conv : to;
79 	import memgraph.enums;
80 
81 	auto tm = mg_time_alloc(&mg_system_allocator);
82 	assert(tm != null);
83 	tm.nanoseconds = 42;
84 	tm.tz_offset_seconds = 23;
85 
86 	auto t = Time(tm);
87 	assert(t.nanoseconds == 42);
88 	assert(t.tz_offset_seconds == 23);
89 
90 	const t1 = t;
91 	assert(t1 == t);
92 
93 	assert(to!string(t) == "42 23");
94 
95 	auto t2 = Time(mg_time_copy(t.ptr));
96 	assert(t2 == t);
97 
98 	const t3 = Time(t2);
99 	assert(t3 == t);
100 
101 	const v = Value(t);
102 	const t4 = Time(v);
103 	assert(t4 == t);
104 	assert(v == t);
105 	assert(to!string(v) == to!string(t));
106 
107 	t2 = t;
108 	assert(t2 == t);
109 
110 	const v1 = Value(t2);
111 	assert(v1.type == Type.Time);
112 	const v2 = Value(t2);
113 	assert(v2.type == Type.Time);
114 
115 	assert(v1 == v2);
116 
117 	const t5 = Time(t3);
118 	assert(t5 == t3);
119 }