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