mxlib
c++ tools for analyzing astronomical data and other tasks by Jared R. Males. [git repo]
Loading...
Searching...
No Matches
timeUtils_test.cpp
Go to the documentation of this file.
1/** \file timeUtils_test.cpp
2 * \brief Tests time and date utilities.
3 */
4#include "../../catch2/catch.hpp"
5
7
8/** \cond */
9namespace
10{
11
12using mx::sys::timeUtilsDetail::operations;
13
14int controlledDatResult = 0;
15int controlledCal2jdResult = 0;
16
17tm *failGmtimeR( const time_t *, tm * )
18{
19 return nullptr;
20}
21
22int controlledDat( int, int, int, double, double *dat )
23{
24 *dat = 37.0;
25 return controlledDatResult;
26}
27
28int controlledCal2jd( int, int, int, double *djm0, double *djm )
29{
30 *djm0 = DJM0;
31 *djm = 57754.0;
32 return controlledCal2jdResult;
33}
34
35class operationsGuard
36{
37 public:
38 operationsGuard() : m_saved( mx::sys::timeUtilsDetail::operationsInstance() )
39 {
40 controlledDatResult = 0;
41 controlledCal2jdResult = 0;
42 }
43
44 ~operationsGuard()
45 {
46 mx::sys::timeUtilsDetail::operationsInstance() = m_saved;
47 }
48
49 private:
50 operations m_saved;
51};
52
53} // namespace
54/** \endcond */
55
56/** Verify operation of get_curr_time.
57 *
58 * This only checks for increasing time on subsequent calls.
59 *
60 */
61/**
62 * \ingroup timeUtils_unit_tests
63 */
64TEST_CASE( "Verify operation of get_curr_time", "[timeutils]" )
65{
66 GIVEN( "getting the time" )
67 {
68 WHEN( "the same timespec is used" )
69 {
70 timespec ts;
71 double t0 = mx::sys::get_curr_time( ts );
72 REQUIRE( t0 > 0 );
73 std::cout << std::endl; // Do something to make sure some time passes.
74 double t1 = mx::sys::get_curr_time( ts );
75
76 REQUIRE( t1 > t0 );
77 }
78
79 WHEN( "no timespec is provided" )
80 {
81 double t0 = mx::sys::get_curr_time();
82 REQUIRE( t0 > 0 );
83 std::cout << std::endl; // Do something to make sure some time passes.
84 double t1 = mx::sys::get_curr_time();
85
86 REQUIRE( t1 > t0 );
87 }
88 }
89}
90
91/** \brief Verifies MJD-to-ISO8601 formatting used for HCI coadd header timestamps.
92 *
93 * \ingroup timeUtils_unit_tests
94 */
95TEST_CASE( "Formatting MJD timestamps as ISO8601", "[timeutils][hciReduce]" )
96{
97 REQUIRE( mx::sys::ISO8601DateTimeStrMJD( 51544.0, 0 ) == "2000-01-01T00:00:00.000000000" );
98 REQUIRE( mx::sys::ISO8601DateTimeStrMJD( 51544.5, 1 ) == "2000-01-01T12:00:00.000000000Z" );
99 REQUIRE( mx::sys::ISO8601DateTimeStrMJD( 51545.0, 2 ) == "2000-01-02T00:00:00.000000000+00:00" );
100}
101
102/** Verify operation of thread sleep functions
103 *
104 * Uses mx::sys::get_curr_time to verify duration of sleep.
105 *
106 */
107/**
108 * \ingroup timeUtils_unit_tests
109 */
110TEST_CASE( "Verify operation of thread sleep functions", "[timeutils]" )
111{
112 GIVEN( "sleeping for 1 second" )
113 {
114 WHEN( "sleeping in seconds" )
115 {
116 double t0 = mx::sys::get_curr_time();
117 mx::sys::sleep( 1 );
118 double t1 = mx::sys::get_curr_time();
119
120 REQUIRE( t1 >= t0 + 1.0 );
121 }
122 WHEN( "sleeping in milliseconds" )
123 {
124 double t0 = mx::sys::get_curr_time();
125 mx::sys::milliSleep( 1000 );
126 double t1 = mx::sys::get_curr_time();
127
128 REQUIRE( t1 >= t0 + 1.0 );
129 }
130 WHEN( "sleeping in microseconds" )
131 {
132 double t0 = mx::sys::get_curr_time();
133 mx::sys::microSleep( 1000000 );
134 double t1 = mx::sys::get_curr_time();
135
136 REQUIRE( t1 >= t0 + 1.0 );
137 }
138 WHEN( "sleeping in nanoseconds" )
139 {
140 double t0 = mx::sys::get_curr_time();
141 mx::sys::nanoSleep( 1000000000 );
142 double t1 = mx::sys::get_curr_time();
143
144 REQUIRE( t1 >= t0 + 1.0 );
145 }
146 }
147}
148
149/** Verify operation of timespecAddNsec
150 *
151 */
152/**
153 * \ingroup timeUtils_unit_tests
154 */
155TEST_CASE( "Verify operation of timespecAddNsec", "[timeutils]" )
156{
157 GIVEN( "a timespec" )
158 {
159 WHEN( "adding less than 1e9 nanoseconds" )
160 {
161 timespec ts;
162 ts.tv_sec = 1;
163 ts.tv_nsec = 0;
164
165 mx::sys::timespecAddNsec( ts, 10 );
166 REQUIRE( ts.tv_sec == 1 );
167 REQUIRE( ts.tv_nsec == 10 );
168
169 mx::sys::timespecAddNsec( ts, 100 );
170 REQUIRE( ts.tv_sec == 1 );
171 REQUIRE( ts.tv_nsec == 110 );
172
173 mx::sys::timespecAddNsec( ts, 1000 );
174 REQUIRE( ts.tv_sec == 1 );
175 REQUIRE( ts.tv_nsec == 1110 );
176
177 mx::sys::timespecAddNsec( ts, 10000 );
178 REQUIRE( ts.tv_sec == 1 );
179 REQUIRE( ts.tv_nsec == 11110 );
180
181 mx::sys::timespecAddNsec( ts, 100000 );
182 REQUIRE( ts.tv_sec == 1 );
183 REQUIRE( ts.tv_nsec == 111110 );
184
185 mx::sys::timespecAddNsec( ts, 1000000 );
186 REQUIRE( ts.tv_sec == 1 );
187 REQUIRE( ts.tv_nsec == 1111110 );
188
189 mx::sys::timespecAddNsec( ts, 10000000 );
190 REQUIRE( ts.tv_sec == 1 );
191 REQUIRE( ts.tv_nsec == 11111110 );
192
193 mx::sys::timespecAddNsec( ts, 100000000 );
194 REQUIRE( ts.tv_sec == 1 );
195 REQUIRE( ts.tv_nsec == 111111110 );
196 }
197
198 WHEN( "adding more than 1e9 nanoseconds but less than 2e9" )
199 {
200 timespec ts;
201 ts.tv_sec = 1;
202 ts.tv_nsec = 0;
203
204 mx::sys::timespecAddNsec( ts, 1000000000 );
205 REQUIRE( ts.tv_sec == 2 );
206 REQUIRE( ts.tv_nsec == 0 );
207
208 mx::sys::timespecAddNsec( ts, 1000000000 + 10 );
209 REQUIRE( ts.tv_sec == 3 );
210 REQUIRE( ts.tv_nsec == 10 );
211
212 mx::sys::timespecAddNsec( ts, 1000000000 + 100 );
213 REQUIRE( ts.tv_sec == 4 );
214 REQUIRE( ts.tv_nsec == 110 );
215
216 mx::sys::timespecAddNsec( ts, 1000000000 + 1000 );
217 REQUIRE( ts.tv_sec == 5 );
218 REQUIRE( ts.tv_nsec == 1110 );
219
220 mx::sys::timespecAddNsec( ts, 1000000000 + 10000 );
221 REQUIRE( ts.tv_sec == 6 );
222 REQUIRE( ts.tv_nsec == 11110 );
223
224 mx::sys::timespecAddNsec( ts, 1000000000 + 100000 );
225 REQUIRE( ts.tv_sec == 7 );
226 REQUIRE( ts.tv_nsec == 111110 );
227
228 mx::sys::timespecAddNsec( ts, 1000000000 + 1000000 );
229 REQUIRE( ts.tv_sec == 8 );
230 REQUIRE( ts.tv_nsec == 1111110 );
231
232 mx::sys::timespecAddNsec( ts, 1000000000 + 10000000 );
233 REQUIRE( ts.tv_sec == 9 );
234 REQUIRE( ts.tv_nsec == 11111110 );
235
236 mx::sys::timespecAddNsec( ts, 1000000000 + 100000000 );
237 REQUIRE( ts.tv_sec == 10 );
238 REQUIRE( ts.tv_nsec == 111111110 );
239 }
240
241 WHEN( "adding more than 2e9" )
242 {
243 timespec ts;
244 ts.tv_sec = 1;
245 ts.tv_nsec = 0;
246
247 mx::sys::timespecAddNsec( ts, 2000000010 );
248 REQUIRE( ts.tv_sec == 3 );
249 REQUIRE( ts.tv_nsec == 10 );
250 }
251
252 WHEN( "the existing nanoseconds cause a carry" )
253 {
254 timespec ts{ 1, 900000000 };
255
256 mx::sys::timespecAddNsec( ts, 200000000 );
257
258 REQUIRE( ts.tv_sec == 2 );
259 REQUIRE( ts.tv_nsec == 100000000 );
260 }
261 }
262}
263
264/** Verify parsing of a formatted time string
265 *
266 * Tests parsing of a string of format hh:mm:ss.s
267 *
268 */
269/**
270 * \ingroup timeUtils_unit_tests
271 */
272TEST_CASE( "Verify parsing of a formatted time string", "[timeutils]" )
273{
274 GIVEN( "a valid time string" )
275 {
276 WHEN( "integer seconds" )
277 {
278 float hr;
279 float mn;
280 float sec;
281
282 mx::sys::parse_hms( hr, mn, sec, "1:2:3" );
283
284 REQUIRE( hr == 1 );
285 REQUIRE( mn == 2 );
286 REQUIRE( sec == 3 );
287 }
288
289 WHEN( "floating seconds" )
290 {
291 float hr;
292 float mn;
293 float sec;
294
295 mx::sys::parse_hms( hr, mn, sec, "1:2:3.23" );
296
297 REQUIRE( hr == 1 );
298 REQUIRE( mn == 2 );
299 REQUIRE_THAT( sec, Catch::Matchers::WithinAbs( 3.23, 1e-7 ) );
300 }
301
302 WHEN( "negative hour" )
303 {
304 float hr;
305 float mn;
306 float sec;
307
308 mx::sys::parse_hms( hr, mn, sec, "-1:2:3.23" );
309
310 REQUIRE( hr == -1 );
311 REQUIRE( mn == -2 );
312 REQUIRE_THAT( sec, Catch::Matchers::WithinAbs( -3.23, 1e-7 ) );
313 }
314
315 WHEN( "0 pads" )
316 {
317 float hr;
318 float mn;
319 float sec;
320
321 mx::sys::parse_hms( hr, mn, sec, "01:02:03.23" );
322
323 REQUIRE( hr == 1 );
324 REQUIRE( mn == 2 );
325 REQUIRE_THAT( sec, Catch::Matchers::WithinAbs( 3.23, 1e-7 ) );
326 }
327 }
328}
329
330/** Verify calculation of MJD
331 *
332 */
333/**
334 * \ingroup timeUtils_unit_tests
335 */
336TEST_CASE( "Verify calculation of MJD", "[timeutils]" )
337{
338 GIVEN( "a valid Gregorian date" )
339 {
340 WHEN( "integer seconds" )
341 {
342 double mjd = mx::sys::Cal2mjd( 2020, 12, 31, 0, 0, 0 );
343 REQUIRE( mjd == 59214.0 );
344 }
345 }
346
347 GIVEN( "a valid Gregorian date" )
348 {
349 WHEN( "floating seconds" )
350 {
351 double mjd = mx::sys::Cal2mjd( 2020, 12, 31, 0, 0, 10.2357 );
352 REQUIRE_THAT( mjd, Catch::Matchers::WithinAbs( 59214.00011846875, 1e-14 ) );
353 }
354 }
355}
356
357/** Verify parsing of an ISO 8601 time string
358 *
359 */
360/**
361 * \ingroup timeUtils_unit_tests
362 */
363TEST_CASE( "Verify parsing of an ISO 8601 time string", "[timeutils]" )
364{
365 GIVEN( "a valid ISO 8601 time string" )
366 {
367 WHEN( "integer seconds" )
368 {
369 int yr, mon, day, hr, min;
370 double sec;
371
372 int rv = mx::sys::ISO8601dateBreakdown( yr, mon, day, hr, min, sec, "2020-12-31T00:00:00" );
373
374 REQUIRE( rv == 0 );
375 REQUIRE( yr == 2020 );
376 REQUIRE( mon == 12 );
377 REQUIRE( day == 31 );
378 REQUIRE( hr == 0 );
379 REQUIRE( min == 0 );
380 REQUIRE( sec == 0 );
381 }
382
383 WHEN( "fractional seconds" )
384 {
385 int yr, mon, day, hr, min;
386 double sec;
387
388 int rv = mx::sys::ISO8601dateBreakdown( yr, mon, day, hr, min, sec, "2020-12-31T00:00:10.2357" );
389
390 REQUIRE( rv == 0 );
391 REQUIRE( yr == 2020 );
392 REQUIRE( mon == 12 );
393 REQUIRE( day == 31 );
394 REQUIRE( hr == 0 );
395 REQUIRE( min == 0 );
396 REQUIRE_THAT( sec, Catch::Matchers::WithinAbs( 10.2357, 1e-14 ) );
397 }
398 }
399
400 GIVEN( "an invalid ISO 8601 time string" )
401 {
402 WHEN( "string too short" )
403 {
404 int yr, mon, day, hr, min;
405 double sec;
406
407 int rv = mx::sys::ISO8601dateBreakdown( yr, mon, day, hr, min, sec, "2020-12-31" );
408
409 REQUIRE( rv == -4 );
410 }
411 }
412}
413
414/** Verify conversion of an ISO 8601 time string to MJD
415 *
416 */
417/**
418 * \ingroup timeUtils_unit_tests
419 */
420TEST_CASE( "Verify conversion of an ISO 8601 time string to MJD", "[timeutils]" )
421{
422 GIVEN( "a valid ISO 8601 time string" )
423 {
424 WHEN( "integer seconds" )
425 {
426 double mjd = mx::sys::ISO8601date2mjd( "2020-12-31T00:00:00" );
427
428 REQUIRE( mjd == 59214.0 );
429 }
430
431 WHEN( "fractional seconds" )
432 {
433 double mjd = mx::sys::ISO8601date2mjd( "2020-12-31T00:00:10.2357" );
434
435 REQUIRE_THAT( mjd, Catch::Matchers::WithinAbs( 59214.00011846875, 1e-14 ) );
436 }
437 }
438
439 GIVEN( "an invalid ISO 8601 time string" )
440 {
441 REQUIRE( mx::sys::ISO8601date2mjd( "2020-12-31" ) == -4 );
442 }
443}
444
445/** \brief Verifies calendar conversion errors are returned to callers.
446 *
447 * \ingroup timeUtils_unit_tests
448 */
449TEST_CASE( "Reject invalid Gregorian calendar dates", "[timeutils]" )
450{
451 REQUIRE( mx::sys::Cal2mjd( -5000, 1, 1, 0, 0, 0 ) == -1 );
452 REQUIRE( mx::sys::Cal2mjd( 2020, 13, 1, 0, 0, 0 ) == -2 );
453 REQUIRE( mx::sys::Cal2mjd( 2020, 2, 31, 0, 0, 0 ) == -3 );
454}
455
456/** \brief Verifies ISO8601 formatting for epoch, fractional, and current timestamps.
457 *
458 * \ingroup timeUtils_unit_tests
459 */
460TEST_CASE( "Format UTC timestamps as ISO8601", "[timeutils]" )
461{
462 const time_t epoch2000 = 946684800;
463 const timespec fractional{ epoch2000, 123456789 };
464
465 REQUIRE( mx::sys::ISO8601DateTimeStr( epoch2000, 0 ) == "2000-01-01T00:00:00" );
466 REQUIRE( mx::sys::ISO8601DateTimeStr( epoch2000, 1 ) == "2000-01-01T00:00:00Z" );
467 REQUIRE( mx::sys::ISO8601DateTimeStr( epoch2000, 2 ) == "2000-01-01T00:00:00+00:00" );
468 REQUIRE( mx::sys::ISO8601DateTimeStr( epoch2000, 3 ) == "2000-01-01T00:00:00" );
469
470 REQUIRE( mx::sys::ISO8601DateTimeStr( fractional, 0 ) == "2000-01-01T00:00:00.123456789" );
471 REQUIRE( mx::sys::ISO8601DateTimeStr( fractional, 1 ) == "2000-01-01T00:00:00.123456789Z" );
472 REQUIRE( mx::sys::ISO8601DateTimeStr( fractional, 2 ) == "2000-01-01T00:00:00.123456789+00:00" );
473
474 REQUIRE( mx::sys::ISO8601DateTimeStr( 0 ).size() == 19 );
475 REQUIRE( mx::sys::ISO8601DateTimeStr( 1 ).size() == 20 );
476 REQUIRE( mx::sys::ISO8601DateTimeStr( 2 ).size() == 25 );
477}
478
479/** \brief Verifies ISO8601 formatting reports broken-down-time failures safely.
480 *
481 * \ingroup timeUtils_unit_tests
482 */
483TEST_CASE( "Handle ISO8601 broken-down-time failures", "[timeutils]" )
484{
485 operationsGuard guard;
486 mx::sys::timeUtilsDetail::operationsInstance().gmtimeR = failGmtimeR;
487
488 const time_t epoch = 0;
489 const timespec fractional{ epoch, 1 };
490
491 REQUIRE( mx::sys::ISO8601DateTimeStr( epoch ).empty() );
492 REQUIRE( mx::sys::ISO8601DateTimeStr( fractional ).empty() );
493}
494
495/** \brief Verifies compact UTC timestamp formatting and its failure result.
496 *
497 * \ingroup timeUtils_unit_tests
498 */
499TEST_CASE( "Format compact UTC timestamps", "[timeutils]" )
500{
501 timespec ts{ 946684800, 123456789 };
502 std::string stamp;
503
504 REQUIRE( mx::sys::timeStamp( stamp, ts ) == 0 );
505 REQUIRE( stamp == "20000101000000123456789" );
506
507 operationsGuard guard;
508 mx::sys::timeUtilsDetail::operationsInstance().gmtimeR = failGmtimeR;
509
510 REQUIRE( mx::sys::timeStamp( stamp, ts ) == -1 );
511}
512
513/** \brief Verifies UTC timespec conversion to split TAI MJD values.
514 *
515 * \ingroup timeUtils_unit_tests
516 */
517TEST_CASE( "Convert UTC timespecs to TAI MJD", "[timeutils]" )
518{
519 double djm = 0;
520 double djmf = 0;
521 tm brokenDown{};
522
523 const timespec epoch2000{ 946684800, 250000000 };
524 REQUIRE( mx::sys::timespecUTC2TAIMJD( djm, djmf, epoch2000, &brokenDown ) == 0 );
525 REQUIRE( djm == 51544.0 );
526 REQUIRE_THAT( djmf, Catch::Matchers::WithinAbs( 32.25 / 86400.0, 1e-15 ) );
527 REQUIRE( brokenDown.tm_year == 100 );
528 REQUIRE( brokenDown.tm_mon == 0 );
529 REQUIRE( brokenDown.tm_mday == 1 );
530
531 const timespec rollover{ 1483315190, 500000000 };
532 REQUIRE( mx::sys::timespecUTC2TAIMJD( djm, djmf, rollover, nullptr ) == 0 );
533 REQUIRE( djm == 57755.0 );
534 REQUIRE_THAT( djmf, Catch::Matchers::WithinAbs( 27.5 / 86400.0, 1e-15 ) );
535}
536
537/** \brief Verifies UTC-to-TAI conversion propagates all external operation failures.
538 *
539 * \ingroup timeUtils_unit_tests
540 */
541TEST_CASE( "Report UTC-to-TAI conversion failures", "[timeutils]" )
542{
543 operationsGuard guard;
544 const timespec ts{ 946684800, 0 };
545 tm brokenDown{};
546 double djm = 0;
547 double djmf = 0;
548
549 mx::sys::timeUtilsDetail::operationsInstance().gmtimeR = failGmtimeR;
550 REQUIRE( mx::sys::timespecUTC2TAIMJD( djm, djmf, ts, &brokenDown ) == -10 );
551
552 mx::sys::timeUtilsDetail::resetOperations();
553 mx::sys::timeUtilsDetail::operationsInstance().iauDat = controlledDat;
554 controlledDatResult = -3;
555 REQUIRE( mx::sys::timespecUTC2TAIMJD( djm, djmf, ts, &brokenDown ) == -3 );
556
557 controlledDatResult = 0;
558 mx::sys::timeUtilsDetail::operationsInstance().iauCal2jd = controlledCal2jd;
559 controlledCal2jdResult = -2;
560 REQUIRE( mx::sys::timespecUTC2TAIMJD( djm, djmf, ts, &brokenDown ) == -2 );
561
562 controlledCal2jdResult = 0;
563 controlledDatResult = 1;
564 REQUIRE( mx::sys::timespecUTC2TAIMJD( djm, djmf, ts, &brokenDown ) == 1 );
565}
566
567/** \brief Verifies averaging normalized timespec values.
568 *
569 * \ingroup timeUtils_unit_tests
570 */
571TEST_CASE( "Average timespec values", "[timeutils]" )
572{
573 timespec mean = mx::sys::meanTimespec( { 0, 0 }, { 2, 0 } );
574 REQUIRE( mean.tv_sec == 1 );
575 REQUIRE( mean.tv_nsec == 0 );
576
577 mean = mx::sys::meanTimespec( { 0, 0 }, { 1, 0 } );
578 REQUIRE( mean.tv_sec == 0 );
579 REQUIRE( mean.tv_nsec == 500000000 );
580
581 mean = mx::sys::meanTimespec( { 0, 900000000 }, { 1, 900000000 } );
582 REQUIRE( mean.tv_sec == 1 );
583 REQUIRE( mean.tv_nsec == 400000000 );
584}
585
586/** \brief Verifies all timespec comparison relations by seconds and nanoseconds.
587 *
588 * \ingroup timeUtils_unit_tests
589 */
590TEST_CASE( "Compare timespec values", "[timeutils]" )
591{
592 const timespec early{ 1, 100 };
593 const timespec laterNsec{ 1, 200 };
594 const timespec laterSec{ 2, 0 };
595 const timespec same{ 1, 100 };
596
597 REQUIRE( mx::sys::tscomp::operator<( early, laterNsec ) );
598 REQUIRE( mx::sys::tscomp::operator<( early, laterSec ) );
599 REQUIRE_FALSE( mx::sys::tscomp::operator<( laterSec, early ) );
600 REQUIRE( mx::sys::tscomp::operator>( laterNsec, early ) );
601 REQUIRE( mx::sys::tscomp::operator>( laterSec, early ) );
602 REQUIRE_FALSE( mx::sys::tscomp::operator>( early, laterSec ) );
603 REQUIRE( mx::sys::tscomp::operator==( early, same ) );
604 REQUIRE_FALSE( mx::sys::tscomp::operator==( early, laterNsec ) );
605 REQUIRE( mx::sys::tscomp::operator<=( early, same ) );
606 REQUIRE( mx::sys::tscomp::operator<=( early, laterNsec ) );
607 REQUIRE_FALSE( mx::sys::tscomp::operator<=( laterNsec, early ) );
608 REQUIRE( mx::sys::tscomp::operator>=( early, same ) );
609 REQUIRE( mx::sys::tscomp::operator>=( laterNsec, early ) );
610 REQUIRE_FALSE( mx::sys::tscomp::operator>=( early, laterNsec ) );
611}
612
613/** \brief Verifies arithmetic addition and subtraction normalize timespec values.
614 *
615 * \ingroup timeUtils_unit_tests
616 */
617TEST_CASE( "Apply arithmetic offsets to timespec values", "[timeutils]" )
618{
619 timespec ts{ 1, 100000000 };
620 timespec result = mx::sys::tsop::operator+( ts, 0.25 );
621 REQUIRE( result.tv_sec == 1 );
622 REQUIRE( result.tv_nsec == 350000000 );
623
624 ts = { 1, 900000000 };
625 result = mx::sys::tsop::operator+( ts, 0.25 );
626 REQUIRE( result.tv_sec == 2 );
627 REQUIRE( result.tv_nsec == 150000000 );
628
629 ts = { 1, 900000000 };
630 result = mx::sys::tsop::operator-( ts, 0.25 );
631 REQUIRE( result.tv_sec == 1 );
632 REQUIRE( result.tv_nsec == 650000000 );
633
634 ts = { 1, 100000000 };
635 result = mx::sys::tsop::operator-( ts, 0.25 );
636 REQUIRE( result.tv_sec == 0 );
637 REQUIRE( result.tv_nsec == 850000000 );
638}
639
640/** \brief Verifies the generic current-time template with a monotonic clock.
641 *
642 * \ingroup timeUtils_unit_tests
643 */
644TEST_CASE( "Read a generic monotonic clock value", "[timeutils]" )
645{
646 timespec ts{};
647 const long double value = mx::sys::get_curr_time<long double, CLOCK_MONOTONIC>( ts );
648
649 REQUIRE( value > 0 );
650 REQUIRE( ts.tv_sec > 0 );
651}
#define DJM0
Julian Date of Modified Julian Date zero (defined in the SOFA library sofam.h).
TEST_CASE("Verify operation of get_curr_time", "[timeutils]")
void nanoSleep(unsigned nsec)
Sleep for a specified period in nanoseconds.
Definition timeUtils.cpp:82
void sleep(unsigned sec)
Sleep for a specified period in seconds.
Definition timeUtils.cpp:67
void milliSleep(unsigned msec)
Sleep for a specified period in milliseconds.
Definition timeUtils.cpp:72
void microSleep(unsigned usec)
Sleep for a specified period in microseconds.
Definition timeUtils.cpp:77
int ISO8601dateBreakdown(int &yr, int &mon, int &day, int &hr, int &min, double &sec, const std::string &fdate)
Parse an ISO8601 date of the form "YYYY-MM-DDTHH:MM:SS.S" into the individual components.
std::string ISO8601DateTimeStr(const timeT &timeIn, int timeZone=0)
Get a date-time string in ISO 8601 format.
std::string ISO8601DateTimeStrMJD(const double &timeIn, int timeZone=0)
Get a date-time string in ISO 8601 format for an MJD.
int timespecUTC2TAIMJD(double &djm, double &djmf, const timespec &tsp, tm *tm0)
Convert a UTC timespec to TAI modified Julian date.
void timespecAddNsec(timespec &ts, unsigned nsec)
Adds a time offset to an existing timespec.
Definition timeUtils.cpp:87
void parse_hms(floatT &h, floatT &m, floatT &s, const std::string &hmsstr)
typeT get_curr_time()
Get the current system time in seconds.
int timeStamp(std::string &tstamp, timespec &ts)
Get a timestamp string in the form YYYYMMDDHHMMSS.SSSSSSSSS.
double Cal2mjd(int yr, int mon, int day, int hr, int min, double sec)
Converts a Gregorian calendar date into modified Julian date (MJD).
Definition timeUtils.cpp:99
double ISO8601date2mjd(const std::string &fdate)
Parse an ISO8601 date of the form "YYYY-MM-DDTHH:MM:SS.S" and return the modified Julian date (MJD).
Utilities for working with time.
timespec operator-(timespec ts, arithT sub)
Subtract an amount of time specified in seconds from a timespec.
timespec operator+(timespec ts, arithT add)
Add an amount of time specified in seconds to a timespec.
timespec meanTimespec(timespec ts1, timespec ts2)
Calculate the mean time of two times given by timespecs.