Line data Source code
1 : /*
2 : * Present - Date/Time Library
3 : *
4 : * Implementation of the ClockTime methods
5 : *
6 : * Licensed under the MIT License.
7 : * For details, see LICENSE.
8 : */
9 :
10 : #include <assert.h>
11 : #include <stddef.h>
12 :
13 : #include "present.h"
14 :
15 : #include "utils/constants.h"
16 : #include "utils/impl-utils.h"
17 : #include "utils/time-utils.h"
18 :
19 : /**
20 : * Initialize a new ClockTime instance based on its data parameters.
21 : */
22 : static void
23 1444 : init_clock_time(
24 : struct ClockTime * const result,
25 : int_hour hour,
26 : int_minute minute,
27 : int_second second,
28 : int_nanosecond nanosecond)
29 : {
30 1444 : assert(result != NULL);
31 1444 : CLEAR(result);
32 :
33 1444 : if (hour == 24) hour = 0;
34 1444 : if (hour < 0 || hour > 24) {
35 5 : result->has_error = 1;
36 5 : result->errors.hour_out_of_range = 1;
37 : }
38 :
39 1444 : if (minute < 0 || minute >= 60) {
40 5 : result->has_error = 1;
41 5 : result->errors.minute_out_of_range = 1;
42 : }
43 :
44 : /* 61 because of leap seconds :( */
45 1444 : if (second < 0 || second >= 61) {
46 9 : result->has_error = 1;
47 9 : result->errors.second_out_of_range = 1;
48 : }
49 :
50 1444 : if (nanosecond < 0 || nanosecond >= NANOSECONDS_IN_SECOND) {
51 4 : result->has_error = 1;
52 4 : result->errors.nanosecond_out_of_range = 1;
53 : }
54 :
55 1444 : if (!result->has_error) {
56 2846 : result->data_.seconds = second +
57 2846 : minute * SECONDS_IN_MINUTE +
58 1423 : hour * SECONDS_IN_HOUR;
59 1423 : result->data_.nanoseconds = nanosecond;
60 : }
61 1444 : }
62 :
63 : /**
64 : * Check the bounds on data.{nanosecond,second} and modify or wrap around if
65 : * necessary.
66 : */
67 : static void
68 13 : check_clock_time(struct ClockTime * const self)
69 : {
70 : #define d self->data_
71 13 : if (d.nanoseconds >= NANOSECONDS_IN_SECOND) {
72 1 : d.seconds += d.nanoseconds / NANOSECONDS_IN_SECOND;
73 1 : d.nanoseconds %= NANOSECONDS_IN_SECOND;
74 : }
75 27 : while (d.nanoseconds < 0) {
76 1 : d.seconds -= 1;
77 1 : d.nanoseconds += NANOSECONDS_IN_SECOND;
78 : }
79 :
80 13 : if (d.seconds >= SECONDS_IN_DAY) {
81 1 : d.seconds %= SECONDS_IN_DAY;
82 : }
83 27 : while (d.seconds < 0) {
84 1 : d.seconds += SECONDS_IN_DAY;
85 : }
86 : #undef d
87 13 : }
88 :
89 :
90 : struct ClockTime
91 3 : ClockTime_from_hour(int_hour hour)
92 : {
93 : struct ClockTime result;
94 3 : init_clock_time(&result, hour, 0, 0, 0);
95 3 : return result;
96 : }
97 :
98 : void
99 9 : ClockTime_ptr_from_hour(struct ClockTime * const result, int_hour hour)
100 : {
101 9 : init_clock_time(result, hour, 0, 0, 0);
102 9 : }
103 :
104 : struct ClockTime
105 3 : ClockTime_from_hour_minute(int_hour hour, int_minute minute)
106 : {
107 : struct ClockTime result;
108 3 : init_clock_time(&result, hour, minute, 0, 0);
109 3 : return result;
110 : }
111 :
112 : void
113 10 : ClockTime_ptr_from_hour_minute(
114 : struct ClockTime * const result,
115 : int_hour hour,
116 : int_minute minute)
117 : {
118 10 : init_clock_time(result, hour, minute, 0, 0);
119 10 : }
120 :
121 : struct ClockTime
122 3 : ClockTime_from_hour_minute_second(
123 : int_hour hour,
124 : int_minute minute,
125 : int_second second)
126 : {
127 : struct ClockTime result;
128 3 : init_clock_time(&result, hour, minute, second, 0);
129 3 : return result;
130 : }
131 :
132 : void
133 164 : ClockTime_ptr_from_hour_minute_second(
134 : struct ClockTime * const result,
135 : int_hour hour,
136 : int_minute minute,
137 : int_second second)
138 : {
139 164 : init_clock_time(result, hour, minute, second, 0);
140 164 : }
141 :
142 : struct ClockTime
143 3 : ClockTime_from_hour_minute_second_nanosecond(
144 : int_hour hour,
145 : int_minute minute,
146 : int_second second,
147 : int_nanosecond nanosecond)
148 : {
149 : struct ClockTime result;
150 3 : init_clock_time(&result, hour, minute, second, nanosecond);
151 3 : return result;
152 : }
153 :
154 : void
155 23 : ClockTime_ptr_from_hour_minute_second_nanosecond(
156 : struct ClockTime * const result,
157 : int_hour hour,
158 : int_minute minute,
159 : int_second second,
160 : int_nanosecond nanosecond)
161 : {
162 23 : init_clock_time(result, hour, minute, second, nanosecond);
163 23 : }
164 :
165 : struct ClockTime
166 2 : ClockTime_create_with_decimal_seconds(
167 : int_hour hour,
168 : int_minute minute,
169 : double second)
170 : {
171 : struct ClockTime result;
172 2 : ClockTime_ptr_create_with_decimal_seconds(&result, hour, minute, second);
173 2 : return result;
174 : }
175 :
176 : void
177 10 : ClockTime_ptr_create_with_decimal_seconds(
178 : struct ClockTime * const result,
179 : int_hour hour,
180 : int_minute minute,
181 : double second)
182 : {
183 : int_second second_int;
184 :
185 10 : second_int = (int_second) second;
186 10 : second = (second - second_int) * (double) NANOSECONDS_IN_SECOND;
187 10 : init_clock_time(result, hour, minute, second_int,
188 10 : (int_nanosecond) present_round(second));
189 10 : }
190 :
191 : struct ClockTime
192 1 : ClockTime_midnight(void)
193 : {
194 : struct ClockTime result;
195 1 : init_clock_time(&result, 0, 0, 0, 0);
196 1 : return result;
197 : }
198 :
199 : void
200 1207 : ClockTime_ptr_midnight(struct ClockTime * const result)
201 : {
202 1207 : init_clock_time(result, 0, 0, 0, 0);
203 1207 : }
204 :
205 : struct ClockTime
206 5 : ClockTime_noon(void)
207 : {
208 : struct ClockTime result;
209 5 : init_clock_time(&result, 12, 0, 0, 0);
210 5 : return result;
211 : }
212 :
213 : void
214 3 : ClockTime_ptr_noon(struct ClockTime * const result)
215 : {
216 3 : init_clock_time(result, 12, 0, 0, 0);
217 3 : }
218 :
219 : int_hour
220 61 : ClockTime_hour(const struct ClockTime * const self)
221 : {
222 61 : assert(self != NULL);
223 61 : assert(self->has_error == 0);
224 :
225 61 : return self->data_.seconds / SECONDS_IN_HOUR;
226 : }
227 :
228 : int_minute
229 97 : ClockTime_minute(const struct ClockTime * const self)
230 : {
231 97 : assert(self != NULL);
232 97 : assert(self->has_error == 0);
233 :
234 97 : return self->data_.seconds % SECONDS_IN_HOUR / SECONDS_IN_MINUTE;
235 : }
236 :
237 : int_second
238 39 : ClockTime_second(const struct ClockTime * const self)
239 : {
240 39 : assert(self != NULL);
241 39 : assert(self->has_error == 0);
242 :
243 39 : return self->data_.seconds % SECONDS_IN_MINUTE;
244 : }
245 :
246 : int_nanosecond
247 38 : ClockTime_nanosecond(const struct ClockTime * const self)
248 : {
249 38 : assert(self != NULL);
250 38 : assert(self->has_error == 0);
251 :
252 38 : return self->data_.nanoseconds;
253 : }
254 :
255 : double
256 60 : ClockTime_second_decimal(const struct ClockTime * const self)
257 : {
258 60 : assert(self != NULL);
259 60 : assert(self->has_error == 0);
260 :
261 120 : return (self->data_.seconds % SECONDS_IN_MINUTE) +
262 60 : ((double)self->data_.nanoseconds / (double)NANOSECONDS_IN_SECOND);
263 : }
264 :
265 : struct TimeDelta
266 1255 : ClockTime_time_since_midnight(const struct ClockTime * const self)
267 : {
268 : struct TimeDelta delta, ns_delta;
269 :
270 1255 : assert(self != NULL);
271 1255 : assert(self->has_error == 0);
272 :
273 1255 : delta = TimeDelta_from_seconds(self->data_.seconds);
274 1255 : ns_delta = TimeDelta_from_nanoseconds(self->data_.nanoseconds);
275 1255 : TimeDelta_add(&delta, &ns_delta);
276 1255 : return delta;
277 : }
278 :
279 : void
280 7 : ClockTime_add_TimeDelta(
281 : struct ClockTime * const self,
282 : const struct TimeDelta * const delta)
283 : {
284 7 : assert(self != NULL);
285 7 : assert(self->has_error == 0);
286 7 : assert(delta != NULL);
287 :
288 7 : self->data_.seconds += delta->data_.delta_seconds;
289 7 : self->data_.nanoseconds += delta->data_.delta_nanoseconds;
290 :
291 7 : check_clock_time(self);
292 7 : }
293 :
294 : void
295 6 : ClockTime_subtract_TimeDelta(
296 : struct ClockTime * const self,
297 : const struct TimeDelta * const delta)
298 : {
299 6 : assert(self != NULL);
300 6 : assert(self->has_error == 0);
301 6 : assert(delta != NULL);
302 :
303 6 : self->data_.seconds -= delta->data_.delta_seconds;
304 6 : self->data_.nanoseconds -= delta->data_.delta_nanoseconds;
305 :
306 6 : check_clock_time(self);
307 6 : }
308 :
309 : short
310 40 : ClockTime_compare(
311 : const struct ClockTime * const lhs,
312 : const struct ClockTime * const rhs)
313 : {
314 40 : assert(lhs != NULL);
315 40 : assert(lhs->has_error == 0);
316 40 : assert(rhs != NULL);
317 40 : assert(rhs->has_error == 0);
318 :
319 121 : return
320 121 : STRUCT_COMPARE(seconds,
321 : STRUCT_COMPARE(nanoseconds, 0));
322 : }
323 :
324 36 : STRUCT_COMPARISON_OPERATORS(ClockTime)
325 :
|