1 // The MIT License (MIT)
2 //
3 // Copyright (c) 2017, 2018 Tomasz Kamiński
4 //
5 // Permission is hereby granted, free of charge, to any person obtaining a copy
6 // of this software and associated documentation files (the "Software"), to deal
7 // in the Software without restriction, including without limitation the rights
8 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 // copies of the Software, and to permit persons to whom the Software is
10 // furnished to do so, subject to the following conditions:
11 //
12 // The above copyright notice and this permission notice shall be included in all
13 // copies or substantial portions of the Software.
14 //
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 // SOFTWARE.
22
23 #include "tz.h"
24 #include <cassert>
25 #include <type_traits>
26
27 //used to count number of conversion
28 int conversions = 0;
29
30 //to/from impl
31 struct mil_clock
32 {
33 using duration = typename std::common_type<std::chrono::system_clock::duration, date::days>::type;
34 using rep = duration::rep;
35 using period = duration::period;
36 using time_point = std::chrono::time_point<mil_clock, duration>;
37
38 static constexpr date::sys_days epoch{date::days{1000}};
39
40 template<typename Duration>
41 static
42 std::chrono::time_point<std::chrono::system_clock, typename std::common_type<Duration, date::days>::type>
to_sysmil_clock43 to_sys(std::chrono::time_point<mil_clock, Duration> const& tp)
44 {
45 ++conversions;
46 return epoch + tp.time_since_epoch();
47 }
48
49 template<typename Duration>
50 static
51 std::chrono::time_point<mil_clock, typename std::common_type<Duration, date::days>::type>
from_sysmil_clock52 from_sys(std::chrono::time_point<std::chrono::system_clock, Duration> const& tp)
53 {
54 ++conversions;
55 using res = std::chrono::time_point<mil_clock, typename std::common_type<Duration, date::days>::type>;
56 return res(tp - epoch);
57 }
58
59 template<typename Duration>
60 static
61 std::chrono::time_point<date::local_t, typename std::common_type<Duration, date::days>::type>
to_localmil_clock62 to_local(std::chrono::time_point<mil_clock, Duration> const& tp)
63 {
64 return date::clock_cast<date::local_t>(to_sys(tp));
65 }
66
67 template<typename Duration>
68 static
69 std::chrono::time_point<mil_clock, typename std::common_type<Duration, date::days>::type>
from_localmil_clock70 from_local(std::chrono::time_point<date::local_t, Duration> const& tp)
71 {
72 return from_sys(date::clock_cast<std::chrono::system_clock>(tp));
73 }
74
75
nowmil_clock76 static time_point now()
77 {
78 return from_sys(std::chrono::system_clock::now());
79 }
80 };
81
82
83 date::sys_days const mil_clock::epoch;
84
85 // traits example
86 struct s2s_clock
87 {
88 using duration = std::chrono::system_clock::duration;
89 using rep = duration::rep;
90 using period = duration::period;
91 using time_point = std::chrono::time_point<s2s_clock, duration>;
92
93 template<typename Duration>
94 static
95 std::chrono::time_point<std::chrono::system_clock, Duration>
to_syss2s_clock96 to_sys(std::chrono::time_point<s2s_clock, Duration> const& tp)
97 {
98 ++conversions;
99 return std::chrono::time_point<std::chrono::system_clock, Duration>(tp.time_since_epoch());
100 }
101
102 template<typename Duration>
103 static
104 std::chrono::time_point<s2s_clock, Duration>
from_syss2s_clock105 from_sys(std::chrono::time_point<std::chrono::system_clock, Duration> const& tp)
106 {
107 ++conversions;
108 return std::chrono::time_point<s2s_clock, Duration>(tp.time_since_epoch());
109 }
110
nows2s_clock111 static time_point now()
112 {
113 return from_sys(std::chrono::system_clock::now());
114 }
115 };
116
117 namespace date
118 {
119 template<>
120 struct clock_time_conversion<mil_clock, s2s_clock>
121 {
122 template<typename Duration>
123 std::chrono::time_point<mil_clock, typename std::common_type<Duration, date::days>::type>
operator ()date::clock_time_conversion124 operator()(std::chrono::time_point<s2s_clock, Duration> const& tp)
125 {
126 ++conversions;
127 using res = std::chrono::time_point<mil_clock, typename std::common_type<Duration, date::days>::type>;
128 return res(tp.time_since_epoch() - mil_clock::epoch.time_since_epoch());
129 }
130 };
131 }
132
133 int
main()134 main()
135 {
136 using namespace date;
137 using sys_clock = std::chrono::system_clock;
138
139 // self
140 {
141 sys_days st(1997_y/dec/12);
142 auto mt = mil_clock::from_sys(st);
143
144 assert(clock_cast<mil_clock>(mt) == mt);
145 }
146
147 // mil <-> local
148 {
149 local_days lt(1997_y/dec/12);
150 auto mt = mil_clock::from_local(lt);
151
152 assert(clock_cast<mil_clock>(lt) == mt);
153 assert(clock_cast<local_t>(mt) == lt);
154 }
155
156 // mil <-> sys
157 {
158 sys_days st(1997_y/dec/12);
159 auto mt = mil_clock::from_sys(st);
160
161 assert(clock_cast<mil_clock>(st) == mt);
162 assert(clock_cast<sys_clock>(mt) == st);
163 }
164
165 // mil <-> utc
166 {
167 sys_days st(1997_y/dec/12);
168 auto mt = mil_clock::from_sys(st);
169 auto ut = utc_clock::from_sys(st);
170
171 assert(clock_cast<mil_clock>(ut) == mt);
172 assert(clock_cast<utc_clock>(mt) == ut);
173 }
174
175 // mil <-> tai
176 {
177 sys_days st(1997_y/dec/12);
178 auto mt = mil_clock::from_sys(st);
179 auto ut = utc_clock::from_sys(st);
180 auto tt = tai_clock::from_utc(ut);
181
182 assert(clock_cast<tai_clock>(mt) == tt);
183 assert(clock_cast<mil_clock>(tt) == mt);
184 }
185
186 // mil <-> gps
187 {
188 sys_days st(1997_y/dec/12);
189 auto mt = mil_clock::from_sys(st);
190 auto ut = utc_clock::from_sys(st);
191 auto gt = gps_clock::from_utc(ut);
192
193 assert(clock_cast<gps_clock>(mt) == gt);
194 assert(clock_cast<mil_clock>(gt) == mt);
195 }
196
197 // s2s -> mil
198 {
199 sys_days st(1997_y/dec/12);
200 auto mt = mil_clock::from_sys(st);
201 auto s2t = s2s_clock::from_sys(st);
202
203 //direct trait conversion
204 conversions = 0;
205 assert(clock_cast<mil_clock>(s2t) == mt);
206 assert(conversions == 1);
207
208 //uses sys_clock
209 conversions = 0;
210 assert(clock_cast<s2s_clock>(mt) == s2t);
211 assert(conversions == 2);
212 }
213 }
214