INSTINCT Code Coverage Report


Directory: src/
File: Navigation/Time/InsTime.hpp
Date: 2025-06-02 15:19:59
Exec Total Coverage
Lines: 406 434 93.5%
Functions: 78 81 96.3%
Branches: 299 387 77.3%

Line Branch Exec Source
1 // This file is part of INSTINCT, the INS Toolkit for Integrated
2 // Navigation Concepts and Training by the Institute of Navigation of
3 // the University of Stuttgart, Germany.
4 //
5 // This Source Code Form is subject to the terms of the Mozilla Public
6 // License, v. 2.0. If a copy of the MPL was not distributed with this
7 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
8
9 /// @file InsTime.hpp
10 /// @brief The class is responsible for all time-related tasks
11 /// @author T. Topp (topp@ins.uni-stuttgart.de)
12 /// @author T. Lambertus (tomke-jantje.lambertus@nav.uni-stuttgart.de)
13 /// @date 2020-12-02
14 ///
15 /// @details This class contains all time-transformations functions. One instance is created for each InsTime object (defined in the structs).
16 /// Internally, only the MJD-time (Modified Julien Date) is stored (here MJD is a struct which has mjd_day and mjd_frac).
17
18 #pragma once
19
20 #include <cstdint>
21 #include <string>
22 #include <array>
23 #include <limits>
24 #include <iostream>
25 #include <chrono>
26
27 #include <fmt/ostream.h>
28 #include "gcem.hpp"
29
30 #include <nlohmann/json.hpp>
31 using json = nlohmann::json; ///< json namespace
32
33 #include "TimeSystem.hpp"
34 #include "Navigation/Math/Math.hpp"
35
36 namespace NAV
37 {
38 /// @brief Utility Namespace for Time related tasks
39 namespace InsTimeUtil
40 {
41 constexpr int32_t END_OF_THE_CENTURY_MJD = 400000; ///< Modified Julian Date of the end of the century (15.01.2954)
42 constexpr int32_t WEEKS_PER_GPS_CYCLE = 1024; ///< Weeks per GPS cycle
43 constexpr int32_t DIFF_TO_6_1_1980_MJD = 44244; ///< 06.01.1980 in Modified Julian Date
44 constexpr int32_t DIFF_TO_1_1_1970_MJD = 40587; ///< 01.01.1970 00:00:00 UTC in Modified Julian Date (UNIX epoch)
45 constexpr int32_t DIFF_BDT_WEEK_TO_GPST_WEEK = 1356; ///< BeiDou starts zero at 1-Jan-2006 and GPS starts 6-Jan-1980
46
47 constexpr int32_t DIFF_MJD_TO_JD_DAYS = 2400000; ///< Difference of the days between MJD and JD
48 constexpr long double DIFF_MJD_TO_JD_FRAC = 0.5L; ///< Difference of the fraction between MJD and JD
49
50 constexpr int32_t MONTHS_PER_YEAR = 12; ///< Months / Year
51 constexpr int32_t DAYS_PER_YEAR = 365; ///< Days / Year
52 constexpr int32_t DAYS_PER_WEEK = 7; ///< Days / Week
53 constexpr int32_t HOURS_PER_DAY = 24; ///< Hours / Day
54 constexpr int32_t HOURS_PER_WEEK = HOURS_PER_DAY * DAYS_PER_WEEK; ///< Hours / Week
55 constexpr int32_t MINUTES_PER_HOUR = 60; ///< Minutes / Hour
56 constexpr int32_t MINUTES_PER_DAY = MINUTES_PER_HOUR * HOURS_PER_DAY; ///< Minutes / Day
57 constexpr int32_t MINUTES_PER_WEEK = MINUTES_PER_DAY * DAYS_PER_WEEK; ///< Minutes / Week
58 constexpr int32_t SECONDS_PER_MINUTE = 60; ///< Seconds / Minute
59 constexpr int32_t SECONDS_PER_HOUR = SECONDS_PER_MINUTE * MINUTES_PER_HOUR; ///< Seconds / Hour
60 constexpr int32_t SECONDS_PER_DAY = SECONDS_PER_MINUTE * MINUTES_PER_HOUR * HOURS_PER_DAY; ///< Seconds / Day
61 constexpr int32_t SECONDS_PER_WEEK = SECONDS_PER_DAY * DAYS_PER_WEEK; ///< Seconds / Week
62
63 /// Numerical precision/epsilon for 'long double' variables
64 /// - Linux/x64: 1e-19
65 /// - Windows/x64 1e-16
66 /// - Linux/armv8: 1e-34 (Epsilon reports too small precision. Real precision is only approx. 1e-17)
67 constexpr long double EPSILON = std::max(1e-17L, 10 * std::numeric_limits<long double>::epsilon());
68
69 /// Maps GPS leap seconds to a time: array<mjd_day>, index + 1 is amount of leap seconds
70 constexpr std::array<int32_t, 20> GPS_LEAP_SEC_MJD = {
71 0, // + 0 at 1 Jan 1980 and before
72 44786, // + 1 at 1 Jul 1981 = diff UTC-TAI: 20
73 45151, // + 2 at 1 Jul 1982 = diff UTC-TAI: 21
74 45516, // + 3 at 1 Jul 1983 = diff UTC-TAI: 22
75 46247, // + 4 at 1 Jul 1985 = diff UTC-TAI: 23
76 47161, // + 5 at 1 Jan 1988 = diff UTC-TAI: 24
77 47892, // + 6 at 1 Jan 1990 = diff UTC-TAI: 25
78 48257, // + 7 at 1 Jan 1991 = diff UTC-TAI: 26
79 48804, // + 8 at 1 Jul 1992 = diff UTC-TAI: 27
80 49169, // + 9 at 1 Jul 1993 = diff UTC-TAI: 28
81 49534, // +10 at 1 Jul 1994 = diff UTC-TAI: 29
82 50083, // +11 at 1 Jan 1996 = diff UTC-TAI: 30
83 50630, // +12 at 1 Jul 1997 = diff UTC-TAI: 31
84 51179, // +13 at 1 Jan 1999 = diff UTC-TAI: 32
85 53736, // +14 at 1 Jan 2006 = diff UTC-TAI: 33
86 54832, // +15 at 1 Jan 2009 = diff UTC-TAI: 34
87 56109, // +16 at 1 Jul 2012 = diff UTC-TAI: 35
88 57204, // +17 at 1 Jul 2015 = diff UTC-TAI: 36
89 57754, // +18 at 1 Jan 2017 = diff UTC-TAI: 37
90 99999, // future
91 };
92
93 /// @brief Returns true if the provided year is a leap year, false otherwise
94 /// @param[in] year The year to check
95 /// @return True if the year is a leap year, otherwise false
96 818472 constexpr bool isLeapYear(int32_t year)
97 {
98
6/6
✓ Branch 0 taken 187295 times.
✓ Branch 1 taken 631177 times.
✓ Branch 2 taken 14377 times.
✓ Branch 3 taken 172918 times.
✓ Branch 4 taken 14316 times.
✓ Branch 5 taken 631238 times.
818472 return (((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0));
99 }
100
101 /// @brief Returns the number of days in the specified month of the year
102 /// @param[in] month Month [1-12]
103 /// @param[in] year Year to determine the leap year
104 /// @return Number of days in the specified month
105 243865 constexpr int32_t daysInMonth(int32_t month, int32_t year)
106 {
107 243865 --month; // Make month 0 based
108
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 243859 times.
243865 if (month >= InsTimeUtil::MONTHS_PER_YEAR)
109 {
110 6 year += month / InsTimeUtil::MONTHS_PER_YEAR;
111 6 month %= InsTimeUtil::MONTHS_PER_YEAR;
112 }
113
2/2
✓ Branch 0 taken 3010 times.
✓ Branch 1 taken 243865 times.
246875 while (month < 0)
114 {
115 3010 month += MONTHS_PER_YEAR;
116 3010 year--;
117 }
118 243865 ++month; // Make month 1 based
119
120
13/13
✓ Branch 0 taken 96588 times.
✓ Branch 1 taken 16543 times.
✓ Branch 2 taken 11081 times.
✓ Branch 3 taken 8312 times.
✓ Branch 4 taken 7246 times.
✓ Branch 5 taken 38774 times.
✓ Branch 6 taken 5829 times.
✓ Branch 7 taken 16016 times.
✓ Branch 8 taken 9284 times.
✓ Branch 9 taken 9022 times.
✓ Branch 10 taken 10647 times.
✓ Branch 11 taken 14521 times.
✓ Branch 12 taken 2 times.
243865 switch (month)
121 {
122 96588 case 1:
123 96588 return 31;
124 16543 case 2:
125
2/2
✓ Branch 1 taken 13146 times.
✓ Branch 2 taken 3397 times.
16543 if (isLeapYear(year))
126 {
127 13146 return 29;
128 }
129 3397 return 28;
130 11081 case 3:
131 11081 return 31;
132 8312 case 4:
133 8312 return 30;
134 7246 case 5:
135 7246 return 31;
136 38774 case 6:
137 38774 return 30;
138 5829 case 7:
139 5829 return 31;
140 16016 case 8:
141 16016 return 31;
142 9284 case 9:
143 9284 return 30;
144 9022 case 10:
145 9022 return 31;
146 10647 case 11:
147 10647 return 30;
148 14521 case 12:
149 14521 return 31;
150 2 default:
151 2 return 366;
152 }
153 }
154
155 /// @brief Formats a duration given in seconds into days, hours, minutes and seconds
156 /// @param[in] seconds Amount of seconds
157 /// @param[in] digits Digits to round the seconds to
158 /// @return Formatted string of the duration
159 12 constexpr std::string formatDuration(double seconds, size_t digits = 9)
160 {
161 12 std::string str;
162
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 8 times.
12 if (seconds >= SECONDS_PER_DAY)
163 {
164 4 auto days = static_cast<int32_t>(seconds) / SECONDS_PER_DAY;
165
2/4
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 4 times.
✗ Branch 6 not taken.
8 str += fmt::format("{}{:d}d", str.empty() ? "" : " ", days);
166 4 seconds -= days * SECONDS_PER_DAY;
167 }
168
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 8 times.
12 if (seconds >= SECONDS_PER_HOUR)
169 {
170 4 auto hours = static_cast<int32_t>(seconds) / SECONDS_PER_HOUR;
171
3/4
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
✓ Branch 5 taken 4 times.
✗ Branch 6 not taken.
8 str += fmt::format("{}{:d}h", str.empty() ? "" : " ", hours);
172 4 seconds -= hours * SECONDS_PER_HOUR;
173 }
174
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 8 times.
12 if (seconds >= SECONDS_PER_MINUTE)
175 {
176 4 auto minutes = static_cast<int32_t>(seconds) / SECONDS_PER_MINUTE;
177
3/4
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
✓ Branch 5 taken 4 times.
✗ Branch 6 not taken.
8 str += fmt::format("{}{:d}m", str.empty() ? "" : " ", minutes);
178 4 seconds -= minutes * SECONDS_PER_MINUTE;
179 }
180
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
12 if (seconds > 1e-9)
181 {
182 6 size_t d = 0;
183
1/2
✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
30 for (; d < digits + 1; d++)
184 {
185 30 if (2.0 * std::abs(std::round(seconds * std::pow(10.0, d)) - seconds * std::pow(10.0, d))
186
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 24 times.
30 < std::pow(10.0, -(static_cast<double>(digits) - static_cast<double>(d))))
187 {
188 6 break;
189 }
190 }
191
3/4
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 2 times.
✓ Branch 5 taken 6 times.
✗ Branch 6 not taken.
12 str += fmt::format("{}{:.{}f}s", str.empty() ? "" : " ", seconds, d);
192 }
193 12 return str;
194 }
195
196 } // namespace InsTimeUtil
197
198 /// Modified Julien Date [UTC]
199 struct InsTime_MJD
200 {
201 int32_t mjd_day = 0; ///< Full days since 17. November 1858 [UTC]
202 long double mjd_frac = 0.0L; ///< Decimal fractions of a day of the Modified Julien Date [UTC]
203
204 /// @brief Default constructor
205 772179 constexpr InsTime_MJD() = default;
206
207 /// @brief Constructor
208 /// @param[in] mjd_day Full days of the Modified Julien Date [UTC]
209 /// @param[in] mjd_frac Decimal fractions of a day of the Modified Julien Date [UTC]
210 1293175 constexpr InsTime_MJD(int32_t mjd_day, long double mjd_frac)
211 1293175 : mjd_day(mjd_day), mjd_frac(mjd_frac)
212 {
213
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1293172 times.
1293175 if (this->mjd_frac >= 1.0L)
214 {
215 3 this->mjd_day += static_cast<int32_t>(this->mjd_frac);
216 3 this->mjd_frac -= static_cast<int32_t>(this->mjd_frac);
217 }
218
2/2
✓ Branch 0 taken 167050 times.
✓ Branch 1 taken 1293175 times.
1460225 while (this->mjd_frac < 0.0L)
219 {
220 167050 this->mjd_frac += 1.0L;
221 167050 this->mjd_day--;
222 }
223 1293175 }
224
225 /// @brief Equal comparison operator (takes double precision into account)
226 /// @param[in] rhs Right-hand side to compare with
227 /// @return Comparison result
228 7389173 constexpr bool operator==(const InsTime_MJD& rhs) const
229 {
230
2/2
✓ Branch 0 taken 7354412 times.
✓ Branch 1 taken 34761 times.
7389173 if (mjd_day == rhs.mjd_day)
231 {
232 7354412 auto difference = gcem::abs(mjd_frac - rhs.mjd_frac);
233 7354162 return difference <= InsTimeUtil::EPSILON;
234 }
235 69581 if (auto diffDays = mjd_day - rhs.mjd_day;
236
2/2
✓ Branch 1 taken 82 times.
✓ Branch 2 taken 34738 times.
34761 gcem::abs(diffDays) == 1)
237 {
238 82 auto difference = 1 + diffDays * (mjd_frac - rhs.mjd_frac);
239 82 return difference <= InsTimeUtil::EPSILON;
240 }
241 34738 return false;
242 }
243 /// @brief Inequal comparison operator (takes double precision into account)
244 /// @param[in] rhs Right-hand side to compare with
245 /// @return Comparison result
246 239957 constexpr bool operator!=(const InsTime_MJD& rhs) const
247 {
248 239957 return !(*this == rhs);
249 }
250 /// @brief Smaller or equal comparison operator (takes double precision into account)
251 /// @param[in] rhs Right-hand side to compare with
252 /// @return Comparison result
253 20 constexpr bool operator<=(const InsTime_MJD& rhs) const
254 {
255
3/4
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 12 times.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
20 return *this < rhs || *this == rhs;
256 }
257 /// @brief Greater or equal comparison operator (takes double precision into account)
258 /// @param[in] rhs Right-hand side to compare with
259 /// @return Comparison result
260 8 constexpr bool operator>=(const InsTime_MJD& rhs) const
261 {
262
3/4
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 4 times.
8 return *this > rhs || *this == rhs;
263 }
264 /// @brief Smaller comparison operator (takes double precision into account)
265 /// @param[in] rhs Right-hand side to compare with
266 /// @return Comparison result
267 1059318 constexpr bool operator<(const InsTime_MJD& rhs) const
268 {
269
3/4
✓ Branch 0 taken 1059359 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 239810 times.
✓ Branch 3 taken 819549 times.
1059354 return (mjd_day < rhs.mjd_day || (mjd_day == rhs.mjd_day && mjd_frac < rhs.mjd_frac))
270
3/4
✓ Branch 0 taken 1059354 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 238761 times.
✓ Branch 4 taken 1074 times.
2118672 && *this != rhs;
271 }
272 /// @brief Greater comparison operator (takes double precision into account)
273 /// @param[in] rhs Right-hand side to compare with
274 /// @return Comparison result
275 12 constexpr bool operator>(const InsTime_MJD& rhs) const
276 {
277 12 return !(*this <= rhs);
278 }
279
280 /// @brief Converts the object into a readable string
281 explicit operator std::string() const;
282 };
283
284 /// Julien Date [UTC]
285 struct InsTime_JD
286 {
287 int32_t jd_day{}; ///< Full days since 1. January −4712 [UTC]
288 long double jd_frac{}; ///< Decimal fractions of a day of the Julien Date [UTC]
289
290 /// @brief Constructor
291 /// @param[in] jd_day Full days of the Julien Date [UTC]
292 /// @param[in] jd_frac Decimal fractions of a day of the Julien Date [UTC]
293 243622 constexpr InsTime_JD(int32_t jd_day, long double jd_frac)
294 243622 : jd_day(jd_day), jd_frac(jd_frac)
295 {
296
2/2
✓ Branch 0 taken 21124 times.
✓ Branch 1 taken 222498 times.
243622 if (this->jd_frac >= 1.0L)
297 {
298 21124 this->jd_day += static_cast<int32_t>(this->jd_frac);
299 21124 this->jd_frac -= static_cast<int32_t>(this->jd_frac);
300 }
301
2/2
✓ Branch 0 taken 138910 times.
✓ Branch 1 taken 243622 times.
382532 while (this->jd_frac < 0.0L)
302 {
303 138910 this->jd_frac += 1.0L;
304 138910 this->jd_day--;
305 }
306 243622 }
307
308 /// @brief Equal comparison operator (takes double precision into account)
309 /// @param[in] rhs Right-hand side to compare with
310 /// @return Comparison result
311 56 constexpr bool operator==(const InsTime_JD& rhs) const
312 {
313
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 20 times.
56 if (jd_day == rhs.jd_day)
314 {
315 36 auto difference = gcem::abs(jd_frac - rhs.jd_frac);
316 36 return difference <= InsTimeUtil::EPSILON;
317 }
318 40 if (auto diffDays = jd_day - rhs.jd_day;
319
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 gcem::abs(diffDays) == 1)
320 {
321 20 auto difference = 1 + diffDays * (jd_frac - rhs.jd_frac);
322 20 return difference <= InsTimeUtil::EPSILON;
323 }
324 return false;
325 }
326 /// @brief Inequal comparison operator (takes double precision into account)
327 /// @param[in] rhs Right-hand side to compare with
328 /// @return Comparison result
329 28 constexpr bool operator!=(const InsTime_JD& rhs) const
330 {
331 28 return !(*this == rhs);
332 }
333 /// @brief Smaller or equal comparison operator (takes double precision into account)
334 /// @param[in] rhs Right-hand side to compare with
335 /// @return Comparison result
336 20 constexpr bool operator<=(const InsTime_JD& rhs) const
337 {
338
3/4
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 12 times.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
20 return *this < rhs || *this == rhs;
339 }
340 /// @brief Greater or equal comparison operator (takes double precision into account)
341 /// @param[in] rhs Right-hand side to compare with
342 /// @return Comparison result
343 8 constexpr bool operator>=(const InsTime_JD& rhs) const
344 {
345
3/4
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 4 times.
8 return *this > rhs || *this == rhs;
346 }
347 /// @brief Smaller comparison operator (takes double precision into account)
348 /// @param[in] rhs Right-hand side to compare with
349 /// @return Comparison result
350 24 constexpr bool operator<(const InsTime_JD& rhs) const
351 {
352
4/4
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 2 times.
16 return (jd_day < rhs.jd_day || (jd_day == rhs.jd_day && jd_frac < rhs.jd_frac))
353
4/4
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 8 times.
✓ Branch 3 taken 16 times.
✓ Branch 4 taken 4 times.
40 && *this != rhs;
354 }
355 /// @brief Greater comparison operator (takes double precision into account)
356 /// @param[in] rhs Right-hand side to compare with
357 /// @return Comparison result
358 12 constexpr bool operator>(const InsTime_JD& rhs) const
359 {
360 12 return !(*this <= rhs);
361 }
362
363 /// @brief Converts the object into a readable string
364 explicit operator std::string() const;
365 };
366
367 /// GPS week and time of week in GPS standard time [GPST]
368 struct InsTime_GPSweekTow
369 {
370 int32_t gpsCycle{}; ///< Contains GPS cycle in GPS standard time [GPST]
371 int32_t gpsWeek{}; ///< Contains GPS week in GPS standard time [GPST]
372 long double tow{}; ///< Contains GPS time of week in seconds in GPS standard time [GPST]
373
374 /// @brief Constructor
375 /// @param[in] gpsCycle GPS cycle in GPS standard time [GPST]
376 /// @param[in] gpsWeek GPS week in GPS standard time [GPST]
377 /// @param[in] tow GPS time of week in seconds in GPS standard time [GPST]
378 224248 constexpr InsTime_GPSweekTow(int32_t gpsCycle, int32_t gpsWeek, long double tow)
379 224248 : gpsCycle(gpsCycle), gpsWeek(gpsWeek), tow(tow)
380 {
381
2/2
✓ Branch 0 taken 122655 times.
✓ Branch 1 taken 101593 times.
224248 if (this->tow >= InsTimeUtil::SECONDS_PER_WEEK)
382 {
383 122655 this->gpsWeek += static_cast<int32_t>(this->tow / InsTimeUtil::SECONDS_PER_WEEK);
384 122655 this->tow = gcem::fmod(this->tow, InsTimeUtil::SECONDS_PER_WEEK);
385 }
386
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 224248 times.
224248 while (this->tow < 0.0L)
387 {
388 this->tow += InsTimeUtil::SECONDS_PER_WEEK;
389 this->gpsWeek--;
390 }
391
392
2/2
✓ Branch 0 taken 194237 times.
✓ Branch 1 taken 30011 times.
224248 if (this->gpsWeek >= InsTimeUtil::WEEKS_PER_GPS_CYCLE)
393 {
394 194237 this->gpsCycle += this->gpsWeek / InsTimeUtil::WEEKS_PER_GPS_CYCLE;
395 194237 this->gpsWeek %= InsTimeUtil::WEEKS_PER_GPS_CYCLE;
396 }
397
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 224248 times.
224248 while (this->gpsWeek < 0)
398 {
399 this->gpsWeek += InsTimeUtil::WEEKS_PER_GPS_CYCLE;
400 this->gpsCycle--;
401 }
402 224248 };
403
404 /// @brief Equal comparison operator (takes double precision into account)
405 /// @param[in] rhs Right-hand side to compare with
406 /// @return Comparison result
407 78 constexpr bool operator==(const InsTime_GPSweekTow& rhs) const
408 {
409
4/4
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 20 times.
✓ Branch 2 taken 38 times.
✓ Branch 3 taken 20 times.
78 if (gpsCycle == rhs.gpsCycle && gpsWeek == rhs.gpsWeek)
410 {
411 38 return gcem::abs(tow - rhs.tow) <= InsTimeUtil::EPSILON;
412 }
413 80 if (auto diffWeeks = gpsCycle * InsTimeUtil::WEEKS_PER_GPS_CYCLE + gpsWeek - (rhs.gpsCycle * InsTimeUtil::WEEKS_PER_GPS_CYCLE + rhs.gpsWeek);
414
2/2
✓ Branch 1 taken 26 times.
✓ Branch 2 taken 14 times.
40 gcem::abs(diffWeeks) == 1)
415 {
416 26 return gcem::abs(tow + diffWeeks * InsTimeUtil::SECONDS_PER_WEEK - rhs.tow) <= InsTimeUtil::EPSILON;
417 }
418 14 return false;
419 }
420 /// @brief Inequal comparison operator (takes double precision into account)
421 /// @param[in] rhs Right-hand side to compare with
422 /// @return Comparison result
423 36 constexpr bool operator!=(const InsTime_GPSweekTow& rhs) const
424 {
425 36 return !(*this == rhs);
426 }
427 /// @brief Smaller or equal comparison operator (takes double precision into account)
428 /// @param[in] rhs Right-hand side to compare with
429 /// @return Comparison result
430 30 constexpr bool operator<=(const InsTime_GPSweekTow& rhs) const
431 {
432
3/4
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 18 times.
✓ Branch 4 taken 12 times.
✗ Branch 5 not taken.
30 return *this < rhs || *this == rhs;
433 }
434 /// @brief Greater or equal comparison operator (takes double precision into account)
435 /// @param[in] rhs Right-hand side to compare with
436 /// @return Comparison result
437 12 constexpr bool operator>=(const InsTime_GPSweekTow& rhs) const
438 {
439
3/4
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6 times.
✓ Branch 5 taken 6 times.
12 return *this > rhs || *this == rhs;
440 }
441 /// @brief Smaller comparison operator (takes double precision into account)
442 /// @param[in] rhs Right-hand side to compare with
443 /// @return Comparison result
444 36 constexpr bool operator<(const InsTime_GPSweekTow& rhs) const
445 {
446 36 return (gpsCycle < rhs.gpsCycle
447
4/4
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 8 times.
28 || (gpsCycle == rhs.gpsCycle && gpsWeek < rhs.gpsWeek)
448
6/6
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 16 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 8 times.
✓ Branch 5 taken 8 times.
20 || (gpsCycle == rhs.gpsCycle && gpsWeek == rhs.gpsWeek && tow < rhs.tow))
449
3/4
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 8 times.
✓ Branch 3 taken 24 times.
✗ Branch 4 not taken.
64 && *this != rhs;
450 }
451 /// @brief Greater comparison operator (takes double precision into account)
452 /// @param[in] rhs Right-hand side to compare with
453 /// @return Comparison result
454 18 constexpr bool operator>(const InsTime_GPSweekTow& rhs) const
455 {
456 18 return !(*this <= rhs);
457 }
458
459 /// @brief Converts the object into a readable string
460 explicit operator std::string() const;
461 };
462
463 /// Universal Time Coordinated [UTC]
464 struct InsTime_YMDHMS
465 {
466 int32_t year{}; ///< Contains year in Universal Time Coordinated [UTC]
467 int32_t month{}; ///< Contains month in Universal Time Coordinated [UTC]
468 int32_t day{}; ///< Contains day in Universal Time Coordinated [UTC]
469 int32_t hour{}; ///< Contains hour in Universal Time Coordinated [UTC]
470 int32_t min{}; ///< Contains minute in Universal Time Coordinated [UTC]
471 long double sec{}; ///< Contains second in Universal Time Coordinated [UTC]
472
473 /// @brief Constructor
474 /// @param[in] year Year in Universal Time Coordinated [UTC]
475 /// @param[in] month Month in Universal Time Coordinated (1 = January) [UTC]
476 /// @param[in] day Day in Universal Time Coordinated (1 = first day) [UTC]
477 /// @param[in] hour Hour in Universal Time Coordinated [UTC]
478 /// @param[in] min Minute in Universal Time Coordinated [UTC]
479 /// @param[in] sec Second in Universal Time Coordinated [UTC]
480 /// @param[in] digits Amount of digits for the seconds to round to
481 243730 constexpr InsTime_YMDHMS(int32_t year, int32_t month, int32_t day, int32_t hour, int32_t min, long double sec, int digits = -1)
482 243730 : year(year), month(month), day(day), hour(hour), min(min), sec(sec)
483 {
484
2/2
✓ Branch 0 taken 2147 times.
✓ Branch 1 taken 241583 times.
243730 if (digits >= 0) { this->sec = math::round(this->sec, static_cast<size_t>(digits)); }
485
2/2
✓ Branch 0 taken 62911 times.
✓ Branch 1 taken 180819 times.
243730 if (this->sec >= InsTimeUtil::SECONDS_PER_MINUTE)
486 {
487 62911 this->min += static_cast<int32_t>(this->sec / InsTimeUtil::SECONDS_PER_MINUTE);
488 62911 this->sec = gcem::fmod(this->sec, InsTimeUtil::SECONDS_PER_MINUTE);
489 }
490
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 243730 times.
243730 while (this->sec < 0.0L)
491 {
492 this->sec += InsTimeUtil::SECONDS_PER_MINUTE;
493 this->min--;
494 }
495
2/2
✓ Branch 0 taken 2147 times.
✓ Branch 1 taken 241583 times.
243730 if (digits >= 0) { this->sec = math::round(this->sec, static_cast<size_t>(digits)); }
496
497
2/2
✓ Branch 0 taken 61207 times.
✓ Branch 1 taken 182523 times.
243730 if (this->min >= InsTimeUtil::MINUTES_PER_HOUR)
498 {
499 61207 this->hour += this->min / InsTimeUtil::MINUTES_PER_HOUR;
500 61207 this->min %= InsTimeUtil::MINUTES_PER_HOUR;
501 }
502
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 243730 times.
243730 while (this->min < 0)
503 {
504 this->min += InsTimeUtil::MINUTES_PER_HOUR;
505 this->hour--;
506 }
507
508
2/2
✓ Branch 0 taken 6409 times.
✓ Branch 1 taken 237321 times.
243730 if (this->hour >= InsTimeUtil::HOURS_PER_DAY)
509 {
510 6409 this->day += this->hour / InsTimeUtil::HOURS_PER_DAY;
511 6409 this->hour %= InsTimeUtil::HOURS_PER_DAY;
512 }
513
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 243730 times.
243730 while (this->hour < 0)
514 {
515 this->hour += InsTimeUtil::HOURS_PER_DAY;
516 this->day--;
517 }
518
519
2/2
✓ Branch 1 taken 279094 times.
✓ Branch 2 taken 243727 times.
522824 while (this->day >= InsTimeUtil::DAYS_PER_YEAR + static_cast<int32_t>(InsTimeUtil::isLeapYear(this->year)))
520 {
521 279094 this->day -= InsTimeUtil::DAYS_PER_YEAR + static_cast<int32_t>(InsTimeUtil::isLeapYear(this->year));
522 279094 this->year++;
523 }
524
525
2/2
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 243728 times.
243741 while (this->day > InsTimeUtil::daysInMonth(this->month, this->year))
526 {
527 14 this->day -= InsTimeUtil::daysInMonth(this->month, this->year);
528 14 this->month++;
529 }
530
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 243728 times.
243730 while (this->day < 1)
531 {
532 2 this->month--;
533 2 this->day += InsTimeUtil::daysInMonth(this->month, this->year);
534 }
535
536
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 243728 times.
243734 while (this->month > InsTimeUtil::MONTHS_PER_YEAR)
537 {
538 6 this->month -= InsTimeUtil::MONTHS_PER_YEAR;
539 6 this->year++;
540 }
541
2/2
✓ Branch 0 taken 3006 times.
✓ Branch 1 taken 243728 times.
246734 while (this->month < 1)
542 {
543 3006 this->month += InsTimeUtil::MONTHS_PER_YEAR;
544 3006 this->year--;
545 }
546 243728 }
547
548 /// @brief Equal comparison operator (takes double precision into account)
549 /// @param[in] rhs Right-hand side to compare with
550 /// @return Comparison result
551 162 constexpr bool operator==(const InsTime_YMDHMS& rhs) const
552 {
553
10/10
✓ Branch 0 taken 142 times.
✓ Branch 1 taken 20 times.
✓ Branch 2 taken 128 times.
✓ Branch 3 taken 14 times.
✓ Branch 4 taken 114 times.
✓ Branch 5 taken 14 times.
✓ Branch 6 taken 93 times.
✓ Branch 7 taken 21 times.
✓ Branch 8 taken 86 times.
✓ Branch 9 taken 7 times.
162 if (year == rhs.year && month == rhs.month && day == rhs.day && hour == rhs.hour && min == rhs.min)
554 {
555 86 return gcem::abs(sec - rhs.sec) <= InsTimeUtil::EPSILON;
556 }
557
1/2
✓ Branch 1 taken 76 times.
✗ Branch 2 not taken.
76 InsTime_YMDHMS this_plus = InsTime_YMDHMS(this->year, this->month, this->day, this->hour, this->min, this->sec + 10);
558
1/2
✓ Branch 1 taken 76 times.
✗ Branch 2 not taken.
76 InsTime_YMDHMS rhs_plus = InsTime_YMDHMS(rhs.year, rhs.month, rhs.day, rhs.hour, rhs.min, rhs.sec + 10);
559
10/10
✓ Branch 0 taken 62 times.
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 48 times.
✓ Branch 3 taken 14 times.
✓ Branch 4 taken 34 times.
✓ Branch 5 taken 14 times.
✓ Branch 6 taken 13 times.
✓ Branch 7 taken 21 times.
✓ Branch 8 taken 6 times.
✓ Branch 9 taken 7 times.
76 if (this_plus.year == rhs_plus.year && this_plus.month == rhs_plus.month && this_plus.day == rhs_plus.day && this_plus.hour == rhs_plus.hour && this_plus.min == rhs_plus.min)
560 {
561 6 return gcem::abs(this_plus.sec - rhs_plus.sec) <= InsTimeUtil::EPSILON;
562 }
563 70 return false;
564 }
565 /// @brief Inequal comparison operator (takes double precision into account)
566 /// @param[in] rhs Right-hand side to compare with
567 /// @return Comparison result
568 73 constexpr bool operator!=(const InsTime_YMDHMS& rhs) const
569 {
570 73 return !(*this == rhs);
571 }
572 /// @brief Smaller or equal comparison operator (takes double precision into account)
573 /// @param[in] rhs Right-hand side to compare with
574 /// @return Comparison result
575 62 constexpr bool operator<=(const InsTime_YMDHMS& rhs) const
576 {
577
3/4
✓ Branch 1 taken 26 times.
✓ Branch 2 taken 36 times.
✓ Branch 4 taken 26 times.
✗ Branch 5 not taken.
62 return *this < rhs || *this == rhs;
578 }
579 /// @brief Greater or equal comparison operator (takes double precision into account)
580 /// @param[in] rhs Right-hand side to compare with
581 /// @return Comparison result
582 25 constexpr bool operator>=(const InsTime_YMDHMS& rhs) const
583 {
584
3/4
✓ Branch 1 taken 25 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 13 times.
✓ Branch 5 taken 12 times.
25 return *this > rhs || *this == rhs;
585 }
586 /// @brief Smaller comparison operator (takes double precision into account)
587 /// @param[in] rhs Right-hand side to compare with
588 /// @return Comparison result
589 74 constexpr bool operator<(const InsTime_YMDHMS& rhs) const
590 {
591 74 return (year < rhs.year
592
4/4
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 56 times.
✓ Branch 3 taken 8 times.
66 || (year == rhs.year && month < rhs.month)
593
5/6
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 56 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 48 times.
✓ Branch 5 taken 8 times.
58 || (year == rhs.year && month == rhs.month && day < rhs.day)
594
6/8
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 48 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 48 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 36 times.
✓ Branch 7 taken 12 times.
50 || (year == rhs.year && month == rhs.month && day == rhs.day && hour < rhs.hour)
595
7/10
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 36 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 36 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 36 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 32 times.
✓ Branch 9 taken 4 times.
38 || (year == rhs.year && month == rhs.month && day == rhs.day && hour == rhs.hour && min < rhs.min)
596
8/12
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 32 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 32 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 32 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 32 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 8 times.
✓ Branch 11 taken 24 times.
34 || (year == rhs.year && month == rhs.month && day == rhs.day && hour == rhs.hour && min == rhs.min && sec < rhs.sec))
597
3/4
✓ Branch 0 taken 66 times.
✓ Branch 1 taken 8 times.
✓ Branch 3 taken 48 times.
✗ Branch 4 not taken.
140 && *this != rhs;
598 }
599 /// @brief Greater comparison operator (takes double precision into account)
600 /// @param[in] rhs Right-hand side to compare with
601 /// @return Comparison result
602 37 constexpr bool operator>(const InsTime_YMDHMS& rhs) const
603 {
604 37 return !(*this <= rhs);
605 }
606
607 /// @brief Converts the object into a readable string
608 explicit operator std::string() const;
609 };
610
611 /// GPS year and day of year in GPS standard time [GPST]
612 struct InsTime_YDoySod
613 {
614 int32_t year{}; ///< Contains year in GPS standard time [GPST]
615 int32_t doy{}; ///< Contains day of year in GPS standard time [GPST]
616 long double sod{}; ///< Contains second of day in GPS standard time [GPST]
617
618 /// @brief Constructor
619 /// @param[in] year Year in GPS standard time [GPST]
620 /// @param[in] doy Day of year in GPS standard time [1-365(/366)]
621 /// @param[in] sod Second of day in GPS standard time [GPST]
622 7 constexpr InsTime_YDoySod(int32_t year, int32_t doy, long double sod)
623 7 : year(year), doy(doy), sod(sod)
624 {
625
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (this->sod >= InsTimeUtil::SECONDS_PER_DAY)
626 {
627 this->doy += static_cast<int32_t>(this->sod / InsTimeUtil::SECONDS_PER_DAY);
628 this->sod = gcem::fmod(this->sod, InsTimeUtil::SECONDS_PER_DAY);
629 }
630
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 while (this->sod < 0)
631 {
632 this->sod += InsTimeUtil::SECONDS_PER_DAY;
633 this->doy--;
634 }
635
636
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
7 while (this->doy > InsTimeUtil::DAYS_PER_YEAR + static_cast<int32_t>(InsTimeUtil::isLeapYear(this->year)))
637 {
638 this->doy -= InsTimeUtil::DAYS_PER_YEAR + static_cast<int32_t>(InsTimeUtil::isLeapYear(this->year));
639 this->year++;
640 }
641
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 while (this->doy < 1)
642 {
643 this->doy += InsTimeUtil::DAYS_PER_YEAR + static_cast<int32_t>(InsTimeUtil::isLeapYear(this->year - 1));
644 this->year--;
645 }
646 7 }
647
648 /// @brief Equal comparison operator (takes double precision into account)
649 /// @param[in] rhs Right-hand side to compare with
650 /// @return Comparison result
651 78 constexpr bool operator==(const InsTime_YDoySod& rhs) const
652 {
653
4/4
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 20 times.
✓ Branch 2 taken 44 times.
✓ Branch 3 taken 14 times.
78 if (year == rhs.year && doy == rhs.doy)
654 {
655 44 return gcem::abs(sod - rhs.sod) <= InsTimeUtil::EPSILON;
656 }
657 68 if (auto diffDays = year * InsTimeUtil::DAYS_PER_YEAR + doy - (rhs.year * InsTimeUtil::DAYS_PER_YEAR + rhs.doy);
658
2/2
✓ Branch 1 taken 20 times.
✓ Branch 2 taken 14 times.
34 gcem::abs(diffDays) == 1)
659 {
660 20 auto difference = gcem::abs(sod + diffDays * InsTimeUtil::SECONDS_PER_DAY - rhs.sod);
661 20 return difference <= InsTimeUtil::EPSILON;
662 }
663 14 return false;
664 }
665 /// @brief Inequal comparison operator (takes double precision into account)
666 /// @param[in] rhs Right-hand side to compare with
667 /// @return Comparison result
668 36 constexpr bool operator!=(const InsTime_YDoySod& rhs) const
669 {
670 36 return !(*this == rhs);
671 }
672 /// @brief Smaller or equal comparison operator (takes double precision into account)
673 /// @param[in] rhs Right-hand side to compare with
674 /// @return Comparison result
675 30 constexpr bool operator<=(const InsTime_YDoySod& rhs) const
676 {
677
3/4
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 18 times.
✓ Branch 4 taken 12 times.
✗ Branch 5 not taken.
30 return *this < rhs || *this == rhs;
678 }
679 /// @brief Greater or equal comparison operator (takes double precision into account)
680 /// @param[in] rhs Right-hand side to compare with
681 /// @return Comparison result
682 12 constexpr bool operator>=(const InsTime_YDoySod& rhs) const
683 {
684
3/4
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6 times.
✓ Branch 5 taken 6 times.
12 return *this > rhs || *this == rhs;
685 }
686 /// @brief Smaller comparison operator (takes double precision into account)
687 /// @param[in] rhs Right-hand side to compare with
688 /// @return Comparison result
689 36 constexpr bool operator<(const InsTime_YDoySod& rhs) const
690 {
691 36 return (year < rhs.year
692
4/4
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 8 times.
28 || (year == rhs.year && doy < rhs.doy)
693
5/6
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✓ Branch 5 taken 10 times.
20 || (year == rhs.year && doy == rhs.doy && sod < rhs.sod))
694
3/4
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 8 times.
✓ Branch 3 taken 24 times.
✗ Branch 4 not taken.
64 && *this != rhs;
695 }
696 /// @brief Greater comparison operator (takes double precision into account)
697 /// @param[in] rhs Right-hand side to compare with
698 /// @return Comparison result
699 18 constexpr bool operator>(const InsTime_YDoySod& rhs) const
700 {
701 18 return !(*this <= rhs);
702 }
703
704 /// @brief Converts the object into a readable string
705 explicit operator std::string() const;
706 };
707
708 /// The class is responsible for all time-related tasks
709 class InsTime
710 {
711 public:
712 /* ------------------------------ Constructors ------------------------------ */
713
714 /// @brief Default Constructor
715 477042 constexpr InsTime() = default;
716
717 /// @brief Constructor
718 /// @param[in] mjd Time in Modified Julien Date
719 /// @param[in] timesys Time System in which the previous values are given in
720 31 constexpr explicit InsTime(const InsTime_MJD& mjd, TimeSystem timesys = UTC)
721 31 : _mjd(mjd)
722 {
723
2/4
✓ Branch 1 taken 31 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 31 times.
✗ Branch 6 not taken.
31 *this -= std::chrono::duration<long double>(differenceToUTC(timesys));
724 31 }
725
726 /// @brief Constructor
727 /// @param[in] jd Time in Julien Date
728 /// @param[in] timesys Time System in which the previous values are given in
729 193538 constexpr explicit InsTime(const InsTime_JD& jd, TimeSystem timesys = UTC)
730 193538 : _mjd(jd.jd_day - InsTimeUtil::DIFF_MJD_TO_JD_DAYS, jd.jd_frac - InsTimeUtil::DIFF_MJD_TO_JD_FRAC)
731 {
732
2/4
✓ Branch 1 taken 193526 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 193526 times.
✗ Branch 6 not taken.
193532 *this -= std::chrono::duration<long double>(differenceToUTC(timesys));
733 193526 }
734
735 /// @brief Constructor
736 /// @param[in] gpsWeekTow Time as week and time of week
737 /// @param[in] timesys Time System in which the previous values are given in
738 101618 constexpr explicit InsTime(const InsTime_GPSweekTow& gpsWeekTow, TimeSystem timesys = GPST)
739 101618 {
740 101602 auto mjd_day = static_cast<int32_t>((gpsWeekTow.gpsCycle * InsTimeUtil::WEEKS_PER_GPS_CYCLE + gpsWeekTow.gpsWeek) * InsTimeUtil::DAYS_PER_WEEK
741 101602 + gcem::floor(gpsWeekTow.tow / InsTimeUtil::SECONDS_PER_DAY)
742 101583 + InsTimeUtil::DIFF_TO_6_1_1980_MJD);
743 101583 long double mjd_frac = gcem::fmod(gpsWeekTow.tow, InsTimeUtil::SECONDS_PER_DAY) / InsTimeUtil::SECONDS_PER_DAY;
744
745 101598 _mjd = InsTime_MJD(mjd_day, mjd_frac);
746
747
2/4
✓ Branch 1 taken 101555 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 101531 times.
✗ Branch 6 not taken.
101598 *this -= std::chrono::duration<long double>(differenceToUTC(timesys));
748 101531 }
749
750 /// @brief Constructor
751 /// @param[in] yearMonthDayHMS Time in Universal Time Coordinated
752 /// @param[in] timesys Time System in which the previous values are given in
753 193520 constexpr explicit InsTime(const InsTime_YMDHMS& yearMonthDayHMS, TimeSystem timesys = UTC)
754 193520 {
755 193504 auto a = static_cast<int32_t>((14 - yearMonthDayHMS.month) / static_cast<double>(InsTimeUtil::MONTHS_PER_YEAR));
756 193504 int32_t y = yearMonthDayHMS.year + 4800 - a;
757 193504 int32_t m = yearMonthDayHMS.month + InsTimeUtil::MONTHS_PER_YEAR * a - 3;
758
759 193504 auto jd_day = static_cast<int32_t>(yearMonthDayHMS.day
760 193504 + gcem::floor((153.0 * static_cast<double>(m) + 2.0) / 5.0)
761 193501 + y * InsTimeUtil::DAYS_PER_YEAR
762 193501 + gcem::floor(static_cast<double>(y) / 4.0)
763 193519 - gcem::floor(static_cast<double>(y) / 100.0)
764 193519 + gcem::floor(static_cast<double>(y) / 400.0)
765 193524 - 32045);
766 193524 auto jd_frac = (yearMonthDayHMS.sec
767 193524 + static_cast<long double>(yearMonthDayHMS.min) * InsTimeUtil::SECONDS_PER_MINUTE
768 193524 + static_cast<long double>(yearMonthDayHMS.hour - 12.0) * InsTimeUtil::SECONDS_PER_HOUR)
769 / InsTimeUtil::SECONDS_PER_DAY;
770
771
2/4
✓ Branch 3 taken 193508 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 193523 times.
✗ Branch 8 not taken.
193524 _mjd = InsTime(InsTime_JD(jd_day, jd_frac)).toMJD();
772
773
2/4
✓ Branch 1 taken 193523 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 193524 times.
✗ Branch 6 not taken.
193523 *this -= std::chrono::duration<long double>(differenceToUTC(timesys));
774 193524 }
775
776 /// @brief Constructor
777 /// @param[in] yearDoySod Time as Year, day of year and seconds of day
778 /// @param[in] timesys Time System in which the previous values are given in
779 28 constexpr explicit InsTime(const InsTime_YDoySod& yearDoySod, TimeSystem timesys = UTC)
780 28 {
781 28 auto year = yearDoySod.year;
782 28 auto doy = yearDoySod.doy;
783 28 auto sod = yearDoySod.sod;
784
785 28 int32_t month = 1;
786
2/2
✓ Branch 1 taken 34 times.
✓ Branch 2 taken 28 times.
62 while (doy > InsTimeUtil::daysInMonth(month, year))
787 {
788 34 doy -= InsTimeUtil::daysInMonth(month, year);
789 34 month++;
790 }
791
792
3/6
✓ Branch 2 taken 28 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 28 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 28 times.
✗ Branch 10 not taken.
28 _mjd = InsTime(InsTime_YMDHMS(year, month, doy, 0, 0, sod)).toMJD();
793
794
2/4
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 28 times.
✗ Branch 6 not taken.
28 *this -= std::chrono::duration<long double>(differenceToUTC(timesys));
795 28 }
796
797 /// @brief Constructor
798 /// @param[in] gpsCycle GPS cycle in GPS standard time
799 /// @param[in] gpsWeek GPS week in GPS standard time
800 /// @param[in] tow GPS time of week in GPS standard time
801 /// @param[in] timesys Time System in which the previous values are given in
802 73101 constexpr InsTime(int32_t gpsCycle, int32_t gpsWeek, long double tow, TimeSystem timesys = GPST)
803
1/2
✓ Branch 2 taken 73103 times.
✗ Branch 3 not taken.
73101 : InsTime(InsTime_GPSweekTow(gpsCycle, gpsWeek, tow), timesys) {}
804
805 /// @brief Constructor
806 /// @param[in] year Year
807 /// @param[in] month Month (1 = January)
808 /// @param[in] day Day (1 = first day)
809 /// @param[in] hour Hour
810 /// @param[in] min Minute
811 /// @param[in] sec Second
812 /// @param[in] timesys Time System in which the previous values are given in
813 193452 constexpr InsTime(int32_t year, int32_t month, int32_t day, int32_t hour, int32_t min, long double sec, TimeSystem timesys = UTC)
814
2/4
✓ Branch 1 taken 193448 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 193456 times.
✗ Branch 5 not taken.
193452 : InsTime(InsTime_YMDHMS(year, month, day, hour, min, sec), timesys) {}
815
816 /// @brief Destructor
817 ~InsTime() = default;
818 /// @brief Copy constructor
819 constexpr InsTime(const InsTime&) = default;
820 /// @brief Move constructor
821 constexpr InsTime(InsTime&&) = default;
822 /// @brief Copy assignment operator
823 constexpr InsTime& operator=(const InsTime&) = default;
824 /// @brief Move assignment operator
825 constexpr InsTime& operator=(InsTime&&) = default;
826
827 /* ------------------------ Transformation functions ------------------------ */
828
829 /// @brief Converts this time object into a different format
830 /// @param timesys Time System in which the time should be given
831 /// @return InsTime_MJD structure of the this object
832 223960 [[nodiscard]] constexpr InsTime_MJD toMJD(TimeSystem timesys = UTC) const
833 {
834 223960 long double mjdFrac = _mjd.mjd_frac + static_cast<long double>(differenceToUTC(timesys)) / static_cast<long double>(InsTimeUtil::SECONDS_PER_DAY);
835 223970 return { _mjd.mjd_day, mjdFrac };
836 }
837
838 /// @brief Converts this time object into a different format
839 /// @param timesys Time System in which the time should be given
840 /// @return InsTime_JD structure of the this object
841 50098 [[nodiscard]] constexpr InsTime_JD toJD(TimeSystem timesys = UTC) const
842 {
843 50098 auto jd_day = _mjd.mjd_day + InsTimeUtil::DIFF_MJD_TO_JD_DAYS;
844 50098 auto jd_frac = _mjd.mjd_frac + InsTimeUtil::DIFF_MJD_TO_JD_FRAC;
845
846 50098 jd_frac += static_cast<long double>(differenceToUTC(timesys)) / static_cast<long double>(InsTimeUtil::SECONDS_PER_DAY);
847
848 50098 return { jd_day, jd_frac };
849 }
850
851 /// @brief Converts this time object into a different format
852 /// @param timesys Time System in which the time should be given
853 /// @return InsTime_GPSweekTow structure of the this object
854 122655 [[nodiscard]] constexpr InsTime_GPSweekTow toGPSweekTow(TimeSystem timesys = GPST) const
855 {
856 122655 InsTime_MJD mjd_leap = _mjd;
857 // Convert from UTC to intended time system
858
1/2
✓ Branch 1 taken 122655 times.
✗ Branch 2 not taken.
122655 mjd_leap.mjd_frac += static_cast<long double>(differenceToUTC(timesys)) / static_cast<long double>(InsTimeUtil::SECONDS_PER_DAY);
859
860 // Put everything in the time of week, as it gets splitted in InsTime_GPSweekTow constructor
861 122655 auto tow = static_cast<long double>((mjd_leap.mjd_day - InsTimeUtil::DIFF_TO_6_1_1980_MJD)) * InsTimeUtil::SECONDS_PER_DAY
862 122655 + mjd_leap.mjd_frac * InsTimeUtil::SECONDS_PER_DAY;
863
864 245310 return { 0, 0, tow };
865 }
866
867 /// @brief Converts this time object into a different format
868 /// @param timesys Time System in which the time should be given
869 /// @param digits Amount of digits for the seconds to round to
870 /// @return InsTime_YMDHMS structure of the this object
871 50095 [[nodiscard]] constexpr InsTime_YMDHMS toYMDHMS(TimeSystem timesys = UTC, int digits = -1) const
872 {
873 // transform MJD to JD
874
1/2
✓ Branch 2 taken 50095 times.
✗ Branch 3 not taken.
50095 InsTime_JD jd = toJD();
875 50095 jd.jd_frac = jd.jd_frac + 0.5L;
876
1/2
✓ Branch 1 taken 50095 times.
✗ Branch 2 not taken.
50095 jd.jd_frac += static_cast<long double>(differenceToUTC(timesys)) / static_cast<long double>(InsTimeUtil::SECONDS_PER_DAY);
877
2/2
✓ Branch 0 taken 29000 times.
✓ Branch 1 taken 21095 times.
50095 if (jd.jd_frac >= 1.0L)
878 {
879 29000 jd.jd_day += static_cast<int32_t>(jd.jd_frac);
880 29000 jd.jd_frac -= gcem::floor(jd.jd_frac);
881 }
882 // transform JD to YMDHMS
883 50095 double a = 32044.0 + jd.jd_day;
884 50095 double b = gcem::floor((4.0 * a + 3.0) / 146097.0);
885 50095 double c = a - gcem::floor((b * 146097.0) / 4.0);
886
887 50095 double d = gcem::floor((4.0 * c + 3.0) / 1461.0);
888 50095 double e = c - gcem::floor((1461.0 * d) / 4.0);
889 50095 double m = gcem::floor((5.0 * e + 2.0) / 153.0);
890
891 50095 auto day = static_cast<uint16_t>(e - gcem::floor((153.0 * m + 2.0) / 5.0) + 1);
892 50095 auto month = static_cast<uint16_t>(m + 3 - 12 * gcem::floor(m / 10.0));
893 50095 auto year = static_cast<uint16_t>(b * 100 + d - 4800.0 + gcem::floor(m / 10.0));
894
895 50095 long double sec = jd.jd_frac * InsTimeUtil::SECONDS_PER_DAY;
896
897
1/2
✓ Branch 1 taken 50095 times.
✗ Branch 2 not taken.
100190 return { year, month, day, 0, 0, sec, digits };
898 }
899
900 /// @brief Converts this time object into a different format
901 /// @param timesys Time System in which the time should be given
902 /// @return InsTime_YDoySod structure of the this object
903 4 [[nodiscard]] constexpr InsTime_YDoySod toYDoySod(TimeSystem timesys = UTC) const
904 {
905
1/2
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
4 InsTime_YMDHMS yearMonthDayHMS = toYMDHMS();
906
907 4 auto year = yearMonthDayHMS.year;
908 4 long double sod = static_cast<long double>(yearMonthDayHMS.hour * InsTimeUtil::SECONDS_PER_HOUR
909 4 + yearMonthDayHMS.min * InsTimeUtil::SECONDS_PER_MINUTE)
910 4 + yearMonthDayHMS.sec
911
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 + static_cast<long double>(differenceToUTC(timesys));
912
913 4 int32_t doy = 0;
914
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 4 times.
18 for (int32_t i = 1; i < yearMonthDayHMS.month; i++)
915 {
916 14 doy += InsTimeUtil::daysInMonth(i, year);
917 }
918 4 doy += yearMonthDayHMS.day;
919
920 8 return { year, doy, sod };
921 }
922
923 /// @brief Returns the current time rounded/cutted to a full day (changes time to 0:0:0h UTC of current day)
924 /// @return The rounded/cutted time object
925 [[nodiscard]] constexpr InsTime toFullDay() const
926 {
927 return InsTime(InsTime_MJD(_mjd.mjd_day, 0.0L));
928 }
929
930 /// @brief Converts this time object into a UNIX timestamp in [s]
931 /// @attention Do not pass `long double` to the LOG_... functions, it can loop indefinitely
932 4 [[nodiscard]] constexpr long double toUnixTime() const
933 {
934 4 return static_cast<long double>((_mjd.mjd_day - InsTimeUtil::DIFF_TO_1_1_1970_MJD) * InsTimeUtil::SECONDS_PER_DAY)
935 4 + _mjd.mjd_frac * InsTimeUtil::SECONDS_PER_DAY;
936 }
937
938 /* ----------------------------- Leap functions ----------------------------- */
939
940 /// @brief Returns the current number of leap seconds (offset GPST to UTC)
941 /// @return Number of leap seconds
942 454067 [[nodiscard]] constexpr uint16_t leapGps2UTC() const
943 {
944 454067 return leapGps2UTC(_mjd);
945 }
946
947 /// @brief Returns the number of leap seconds (offset GPST to UTC) for the provided InsTime object
948 /// @param[in] insTime Time point
949 /// @return Number of leap seconds
950 7 static constexpr uint16_t leapGps2UTC(const InsTime& insTime)
951 {
952 7 return leapGps2UTC(insTime._mjd);
953 }
954
955 /// @brief Returns the number of leap seconds (offset GPST to UTC) for the provided InsTime_GPSweekTow object
956 /// @param[in] gpsWeekTow Time point
957 /// @return Number of leap seconds
958 1 static constexpr uint16_t leapGps2UTC(const InsTime_GPSweekTow& gpsWeekTow)
959 {
960
3/6
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
1 return leapGps2UTC(InsTime(gpsWeekTow).toMJD());
961 }
962
963 /// @brief Returns the number of leap seconds (offset GPST to UTC) for the provided InsTime_YDoySod object
964 /// @param[in] yearDoySod Time point
965 /// @return Number of leap seconds
966 1 static constexpr uint16_t leapGps2UTC(const InsTime_YDoySod& yearDoySod)
967 {
968
3/6
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
1 return leapGps2UTC(InsTime(yearDoySod).toMJD());
969 }
970
971 /// @brief Returns the number of leap seconds (offset GPST to UTC) for the provided InsTime_YMDHMS object
972 /// @param[in] yearMonthDayHMS Time point
973 /// @return Number of leap seconds
974 1 static constexpr uint16_t leapGps2UTC(const InsTime_YMDHMS& yearMonthDayHMS)
975 {
976
3/6
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
1 return leapGps2UTC(InsTime(yearMonthDayHMS).toMJD());
977 }
978
979 /// @brief Returns the number of leap seconds (offset GPST to UTC) for the provided InsTime_JD object
980 /// @param[in] jd Time point
981 /// @return Number of leap seconds
982 1 static constexpr uint16_t leapGps2UTC(const InsTime_JD& jd)
983 {
984
3/6
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
1 return leapGps2UTC(InsTime(jd).toMJD());
985 }
986
987 /// @brief Returns the number of leap seconds (offset GPST to UTC) for the provided InsTime_MJD object
988 /// @param[in] mjd_in Time point
989 /// @return Number of leap seconds
990 454065 static constexpr uint16_t leapGps2UTC(const InsTime_MJD& mjd_in)
991 {
992 454065 return static_cast<uint16_t>(std::ranges::upper_bound(InsTimeUtil::GPS_LEAP_SEC_MJD, mjd_in.mjd_day) - InsTimeUtil::GPS_LEAP_SEC_MJD.begin() - 1);
993 }
994
995 /// @brief Checks if the current time is a leap year
996 /// @return True if the current time is a leap year, false otherwise
997 1 [[nodiscard]] constexpr bool isLeapYear() const
998 {
999
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 return InsTimeUtil::isLeapYear(toYMDHMS().year);
1000 }
1001
1002 /* --------------------- Comparison operator overloading -------------------- */
1003
1004 /// @brief Equal comparison operator (takes double precision into account)
1005 /// @param[in] rhs Right-hand side to compare with
1006 /// @return Comparison result
1007 7149291 constexpr bool operator==(const InsTime& rhs) const { return _mjd == rhs._mjd; }
1008 /// @brief Inequal comparison operator (takes double precision into account)
1009 /// @param[in] rhs Right-hand side to compare with
1010 /// @return Comparison result
1011 56 constexpr bool operator!=(const InsTime& rhs) const { return !(*this == rhs); }
1012 /// @brief Smaller or equal comparison operator (takes double precision into account)
1013 /// @param[in] rhs Right-hand side to compare with
1014 /// @return Comparison result
1015
4/4
✓ Branch 1 taken 10266 times.
✓ Branch 2 taken 24627 times.
✓ Branch 4 taken 10072 times.
✓ Branch 5 taken 194 times.
34893 constexpr bool operator<=(const InsTime& rhs) const { return *this < rhs || *this == rhs; }
1016 /// @brief Greater or equal comparison operator (takes double precision into account)
1017 /// @param[in] rhs Right-hand side to compare with
1018 /// @return Comparison result
1019
4/4
✓ Branch 1 taken 67 times.
✓ Branch 2 taken 141 times.
✓ Branch 4 taken 16 times.
✓ Branch 5 taken 51 times.
208 constexpr bool operator>=(const InsTime& rhs) const { return *this > rhs || *this == rhs; }
1020 /// @brief Smaller comparison operator (takes double precision into account)
1021 /// @param[in] rhs Right-hand side to compare with
1022 /// @return Comparison result
1023 1059384 constexpr bool operator<(const InsTime& rhs) const { return _mjd < rhs._mjd; }
1024 /// @brief Greater comparison operator (takes double precision into account)
1025 /// @param[in] rhs Right-hand side to compare with
1026 /// @return Comparison result
1027 27568 constexpr bool operator>(const InsTime& rhs) const { return !(*this <= rhs); }
1028
1029 /* --------------------- Arithmetic operator overloading -------------------- */
1030
1031 /// @brief Substracts 2 points in time
1032 /// @param[in] lhs The left hand side time point
1033 /// @param[in] rhs The right hand side time point
1034 /// @return Time difference in [seconds]
1035 1584867 constexpr friend std::chrono::duration<long double> operator-(const InsTime& lhs, const InsTime& rhs)
1036 {
1037 1584867 auto diffDays = lhs._mjd.mjd_day - rhs._mjd.mjd_day;
1038 1584867 auto diffFrac = lhs._mjd.mjd_frac - rhs._mjd.mjd_frac;
1039 1584867 long double diffSec = (diffFrac + static_cast<long double>(diffDays)) * InsTimeUtil::SECONDS_PER_DAY;
1040 1584867 return std::chrono::duration<long double>(diffSec);
1041 }
1042
1043 /// @brief Adds a duration to this time point
1044 /// @param[in] duration The duration to add
1045 /// @return Reference to this object
1046 141062 constexpr InsTime& operator+=(const std::chrono::duration<long double>& duration)
1047 {
1048
1/2
✓ Branch 1 taken 141066 times.
✗ Branch 2 not taken.
141062 auto duration_mjd_frac = std::chrono::duration<long double, std::ratio<InsTimeUtil::SECONDS_PER_DAY>>(duration).count();
1049 282127 this->_mjd = InsTime_MJD(this->_mjd.mjd_day,
1050 141055 this->_mjd.mjd_frac + duration_mjd_frac);
1051 141072 return *this;
1052 }
1053
1054 /// @brief Substracts a duration to this time point
1055 /// @param[in] duration The duration to substract
1056 /// @return Reference to this object
1057 633035 constexpr InsTime& operator-=(const std::chrono::duration<long double>& duration)
1058 {
1059
1/2
✓ Branch 1 taken 633025 times.
✗ Branch 2 not taken.
633035 auto duration_mjd_frac = std::chrono::duration<long double, std::ratio<InsTimeUtil::SECONDS_PER_DAY>>(duration).count();
1060 1265988 this->_mjd = InsTime_MJD(this->_mjd.mjd_day,
1061 632961 this->_mjd.mjd_frac - duration_mjd_frac);
1062 633027 return *this;
1063 }
1064
1065 /// @brief Adds a duration to a time point
1066 /// @param[in] time The left hand side time point
1067 /// @param[in] duration The right hand side duration
1068 /// @return Time point with the added duration
1069 140101 constexpr friend InsTime operator+(const InsTime& time, const std::chrono::duration<long double>& duration)
1070 {
1071
1/2
✓ Branch 1 taken 140106 times.
✗ Branch 2 not taken.
140101 return InsTime(time) += duration;
1072 }
1073
1074 /// @brief Substracts a duration from a time point
1075 /// @param[in] time The left hand side time point
1076 /// @param[in] duration The right hand side duration
1077 /// @return Time point with the substracted duration
1078 144362 constexpr friend InsTime operator-(const InsTime& time, const std::chrono::duration<long double>& duration)
1079 {
1080
1/2
✓ Branch 1 taken 144362 times.
✗ Branch 2 not taken.
144362 return InsTime(time) -= duration;
1081 }
1082
1083 /* ---------------------------- Utility Functions --------------------------- */
1084
1085 /// @brief Converts the object into a readable string
1086 explicit operator std::string() const;
1087
1088 /// @brief Checks if the Time object has a value
1089 2580780 [[nodiscard]] constexpr bool empty() const
1090 {
1091
4/4
✓ Branch 0 taken 477082 times.
✓ Branch 1 taken 2103698 times.
✓ Branch 2 taken 477068 times.
✓ Branch 3 taken 14 times.
2580780 return _mjd.mjd_day == 0 && _mjd.mjd_frac == 0.0L;
1092 }
1093
1094 /// @brief Resets the InsTime object
1095 220412 void reset()
1096 {
1097 220412 _mjd.mjd_day = 0;
1098 220412 _mjd.mjd_frac = 0.0L;
1099 220412 }
1100
1101 /// @brief Adds the difference [seconds] between toe (OBRIT-0 last element) and toc (ORBIT-0 first element) to the current time
1102 /// (Changes time, so that it corresponds to the time of GLONASS ORBIT last element)
1103 /// @param[in] UTC_sec Seconds in UTC time
1104 void MakeTimeFromGloOrbit(double UTC_sec)
1105 {
1106 auto ymdhms = toYMDHMS();
1107 // difference between toe (OBRIT-0 last element) and toc (ORBIT-0 first element) in seconds
1108 long double diff = gcem::fmod(static_cast<long double>(UTC_sec), InsTimeUtil::SECONDS_PER_DAY)
1109 - (ymdhms.hour * InsTimeUtil::SECONDS_PER_HOUR
1110 + ymdhms.min * InsTimeUtil::SECONDS_PER_MINUTE
1111 + ymdhms.sec);
1112 // std::cout << "orbit diff " << diff << "\n";
1113 *this += std::chrono::duration<long double>(diff);
1114 }
1115
1116 /// @brief Returns the time difference in [s] of a time system and UTC
1117 /// @param[in] timesys Time system to get the difference from UTC
1118 935618 [[nodiscard]] constexpr int differenceToUTC(TimeSystem timesys) const
1119 {
1120
7/8
✓ Branch 1 taken 392820 times.
✓ Branch 2 taken 17 times.
✓ Branch 3 taken 23230 times.
✓ Branch 4 taken 2220 times.
✓ Branch 5 taken 54 times.
✓ Branch 6 taken 20461 times.
✓ Branch 7 taken 496795 times.
✗ Branch 8 not taken.
935618 switch (TimeSystem_(timesys))
1121 {
1122 392820 case GPST: // = GPS Time (UTC + leap_seconds)
1123 392820 return this->leapGps2UTC();
1124 17 case GLNT: // = GLONASS Time (UTC+ 3h)
1125 17 return 3 * InsTimeUtil::SECONDS_PER_HOUR;
1126 23230 case GST: // = GALILEO Time (~ GPS) (UTC = GST - 18) is synchronized with TAI with a nominal offset below 50 ns
1127 23230 return this->leapGps2UTC();
1128 2220 case QZSST:
1129 2220 return this->leapGps2UTC(); // TODO citation for synchronization accuracy
1130 54 case IRNSST:
1131 54 return this->leapGps2UTC(); // TODO citation for synchronization accuracy
1132 20461 case BDT: // = BeiDou Time (UTC) is synchronized with UTC within 100 ns<
1133 20461 return this->leapGps2UTC() - 14;
1134 496795 case UTC:
1135 case TimeSys_None:
1136 496795 return 0;
1137 }
1138 return 0;
1139 }
1140
1141 private:
1142 /// @brief Modified Julien Date of this InsTime object
1143 InsTime_MJD _mjd;
1144 };
1145
1146 /// @brief Stream insertion operator overload
1147 /// @param[in, out] os Output stream object to stream the time into
1148 /// @param[in] mjd Object to print
1149 /// @return Returns the output stream object in order to chain stream insertions
1150 std::ostream& operator<<(std::ostream& os, const InsTime_MJD& mjd);
1151 /// @brief Stream insertion operator overload
1152 /// @param[in, out] os Output stream object to stream the time into
1153 /// @param[in] jd Object to print
1154 /// @return Returns the output stream object in order to chain stream insertions
1155 std::ostream& operator<<(std::ostream& os, const InsTime_JD& jd);
1156 /// @brief Stream insertion operator overload
1157 /// @param[in, out] os Output stream object to stream the time into
1158 /// @param[in] gpsWeekTow Object to print
1159 /// @return Returns the output stream object in order to chain stream insertions
1160 std::ostream& operator<<(std::ostream& os, const InsTime_GPSweekTow& gpsWeekTow);
1161 /// @brief Stream insertion operator overload
1162 /// @param[in, out] os Output stream object to stream the time into
1163 /// @param[in] ymdhms Object to print
1164 /// @return Returns the output stream object in order to chain stream insertions
1165 std::ostream& operator<<(std::ostream& os, const InsTime_YMDHMS& ymdhms);
1166 /// @brief Stream insertion operator overload
1167 /// @param[in, out] os Output stream object to stream the time into
1168 /// @param[in] yDoySod Object to print
1169 /// @return Returns the output stream object in order to chain stream insertions
1170 std::ostream& operator<<(std::ostream& os, const InsTime_YDoySod& yDoySod);
1171 /// @brief Stream insertion operator overload
1172 /// @param[in, out] os Output stream object to stream the time into
1173 /// @param[in] insTime Object to print
1174 /// @return Returns the output stream object in order to chain stream insertions
1175 std::ostream& operator<<(std::ostream& os, const InsTime& insTime);
1176
1177 /// @brief Converts the provided InsTime into a json object
1178 /// @param[out] j Return Json object
1179 /// @param[in] insTime Time to convert
1180 void to_json(json& j, const InsTime& insTime);
1181 /// @brief Converts the provided json object into an InsTime
1182 /// @param[in] j Json object with the time values
1183 /// @param[out] insTime Time to return
1184 void from_json(const json& j, InsTime& insTime);
1185
1186 } // namespace NAV
1187
1188 namespace std
1189 {
1190 /// @brief Hash function for InsTime (needed for unordered_map)
1191 template<>
1192 struct hash<NAV::InsTime>
1193 {
1194 /// @brief Hash function for InsTime
1195 /// @param[in] t Time
1196 std::size_t operator()(const NAV::InsTime& t) const
1197 {
1198 auto hash1 = std::hash<int32_t>{}(t.toMJD().mjd_day);
1199 auto hash2 = std::hash<long double>{}(t.toMJD().mjd_frac);
1200
1201 return hash1 | (hash2 << 32);
1202 }
1203 };
1204 } // namespace std
1205
1206 #ifndef DOXYGEN_IGNORE
1207
1208 /// @brief Formatter
1209 template<>
1210 struct fmt::formatter<NAV::InsTime_MJD> : fmt::formatter<std::string>
1211 {
1212 /// @brief Defines how to format this structs
1213 /// @param[in] mjd Struct to format
1214 /// @param[in, out] ctx Format context
1215 /// @return Output iterator
1216 template<typename FormatContext>
1217 auto format(const NAV::InsTime_MJD& mjd, FormatContext& ctx) const
1218 {
1219 return fmt::format_to(ctx.out(), "day={}, frac={}", mjd.mjd_day, static_cast<double>(mjd.mjd_frac));
1220 }
1221 };
1222 /// @brief Formatter
1223 template<>
1224 struct fmt::formatter<NAV::InsTime_JD> : fmt::formatter<std::string>
1225 {
1226 /// @brief Defines how to format this structs
1227 /// @param[in] jd Struct to format
1228 /// @param[in, out] ctx Format context
1229 /// @return Output iterator
1230 template<typename FormatContext>
1231 auto format(const NAV::InsTime_JD& jd, FormatContext& ctx) const
1232 {
1233 return fmt::format_to(ctx.out(), "day={}, frac={}", jd.jd_day, static_cast<double>(jd.jd_frac));
1234 }
1235 };
1236 /// @brief Formatter
1237 template<>
1238 struct fmt::formatter<NAV::InsTime_GPSweekTow> : fmt::formatter<std::string>
1239 {
1240 /// @brief Defines how to format this structs
1241 /// @param[in] gpsWeekTow Struct to format
1242 /// @param[in, out] ctx Format context
1243 /// @return Output iterator
1244 template<typename FormatContext>
1245 19560 auto format(const NAV::InsTime_GPSweekTow& gpsWeekTow, FormatContext& ctx) const
1246 {
1247 39120 return fmt::format_to(ctx.out(), "cycle={}, week={}, tow={}",
1248 39120 gpsWeekTow.gpsCycle, gpsWeekTow.gpsWeek, static_cast<double>(gpsWeekTow.tow));
1249 }
1250 };
1251 /// @brief Formatter
1252 template<>
1253 struct fmt::formatter<NAV::InsTime_YMDHMS> : fmt::formatter<std::string>
1254 {
1255 /// @brief Defines how to format this structs
1256 /// @param[in] ymdhms Struct to format
1257 /// @param[in, out] ctx Format context
1258 /// @return Output iterator
1259 template<typename FormatContext>
1260 47921 auto format(const NAV::InsTime_YMDHMS& ymdhms, FormatContext& ctx) const
1261 {
1262 95842 return fmt::format_to(ctx.out(), "{}-{}-{} {}:{}:{:.6g}",
1263 47921 ymdhms.year, ymdhms.month, ymdhms.day,
1264 95842 ymdhms.hour, ymdhms.min, static_cast<double>(ymdhms.sec));
1265 }
1266 };
1267 /// @brief Formatter
1268 template<>
1269 struct fmt::formatter<NAV::InsTime_YDoySod> : fmt::formatter<std::string>
1270 {
1271 /// @brief Defines how to format this structs
1272 /// @param[in] yDoySod Struct to format
1273 /// @param[in, out] ctx Format context
1274 /// @return Output iterator
1275 template<typename FormatContext>
1276 auto format(const NAV::InsTime_YDoySod& yDoySod, FormatContext& ctx) const
1277 {
1278 return fmt::format_to(ctx.out(), "year={}, doy={}, sod={:.6g}",
1279 yDoySod.year, yDoySod.doy, static_cast<double>(yDoySod.sod));
1280 }
1281 };
1282 /// @brief Formatter
1283 template<>
1284 struct fmt::formatter<NAV::InsTime> : fmt::formatter<std::string>
1285 {
1286 /// @brief Defines how to format this structs
1287 /// @param[in] insTime Struct to format
1288 /// @param[in, out] ctx Format context
1289 /// @return Output iterator
1290 template<typename FormatContext>
1291 12902 auto format(const NAV::InsTime& insTime, FormatContext& ctx) const
1292 {
1293
2/4
✓ Branch 2 taken 12902 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 12902 times.
✗ Branch 7 not taken.
25804 return fmt::format_to(ctx.out(), "{} ({})", insTime.toYMDHMS(), insTime.toGPSweekTow());
1294 }
1295 };
1296
1297 #endif
1298