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 | 797006 | constexpr bool isLeapYear(int32_t year) | |
97 | { | ||
98 |
6/6✓ Branch 0 taken 166380 times.
✓ Branch 1 taken 630626 times.
✓ Branch 2 taken 14338 times.
✓ Branch 3 taken 152042 times.
✓ Branch 4 taken 14288 times.
✓ Branch 5 taken 630676 times.
|
797006 | 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 | 232637 | constexpr int32_t daysInMonth(int32_t month, int32_t year) | |
106 | { | ||
107 | 232637 | --month; // Make month 0 based | |
108 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 232631 times.
|
232637 | 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 232637 times.
|
235647 | while (month < 0) |
114 | { | ||
115 | 3010 | month += MONTHS_PER_YEAR; | |
116 | 3010 | year--; | |
117 | } | ||
118 | 232637 | ++month; // Make month 1 based | |
119 | |||
120 |
13/13✓ Branch 0 taken 96510 times.
✓ Branch 1 taken 6314 times.
✓ Branch 2 taken 11057 times.
✓ Branch 3 taken 8288 times.
✓ Branch 4 taken 7246 times.
✓ Branch 5 taken 38272 times.
✓ Branch 6 taken 5829 times.
✓ Branch 7 taken 15752 times.
✓ Branch 8 taken 9284 times.
✓ Branch 9 taken 9022 times.
✓ Branch 10 taken 10557 times.
✓ Branch 11 taken 14503 times.
✓ Branch 12 taken 3 times.
|
232637 | switch (month) |
121 | { | ||
122 | 96510 | case 1: | |
123 | 96510 | return 31; | |
124 | 6314 | case 2: | |
125 |
2/2✓ Branch 1 taken 2708 times.
✓ Branch 2 taken 3606 times.
|
6314 | if (isLeapYear(year)) |
126 | { | ||
127 | 2708 | return 29; | |
128 | } | ||
129 | 3606 | return 28; | |
130 | 11057 | case 3: | |
131 | 11057 | return 31; | |
132 | 8288 | case 4: | |
133 | 8288 | return 30; | |
134 | 7246 | case 5: | |
135 | 7246 | return 31; | |
136 | 38272 | case 6: | |
137 | 38272 | return 30; | |
138 | 5829 | case 7: | |
139 | 5829 | return 31; | |
140 | 15752 | case 8: | |
141 | 15752 | return 31; | |
142 | 9284 | case 9: | |
143 | 9284 | return 30; | |
144 | 9022 | case 10: | |
145 | 9022 | return 31; | |
146 | 10557 | case 11: | |
147 | 10557 | return 30; | |
148 | 14503 | case 12: | |
149 | 14503 | return 31; | |
150 | 3 | default: | |
151 | 3 | return 366; | |
152 | } | ||
153 | } | ||
154 | } // namespace InsTimeUtil | ||
155 | |||
156 | /// Modified Julien Date [UTC] | ||
157 | struct InsTime_MJD | ||
158 | { | ||
159 | int32_t mjd_day = 0; ///< Full days since 17. November 1858 [UTC] | ||
160 | long double mjd_frac = 0.0L; ///< Decimal fractions of a day of the Modified Julien Date [UTC] | ||
161 | |||
162 | /// @brief Default constructor | ||
163 | 774746 | constexpr InsTime_MJD() = default; | |
164 | |||
165 | /// @brief Constructor | ||
166 | /// @param[in] mjd_day Full days of the Modified Julien Date [UTC] | ||
167 | /// @param[in] mjd_frac Decimal fractions of a day of the Modified Julien Date [UTC] | ||
168 | 1392552 | constexpr InsTime_MJD(int32_t mjd_day, long double mjd_frac) | |
169 | 1392552 | : mjd_day(mjd_day), mjd_frac(mjd_frac) | |
170 | { | ||
171 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1392549 times.
|
1392552 | if (this->mjd_frac >= 1.0L) |
172 | { | ||
173 | 3 | this->mjd_day += static_cast<int32_t>(this->mjd_frac); | |
174 | 3 | this->mjd_frac -= static_cast<int32_t>(this->mjd_frac); | |
175 | } | ||
176 |
2/2✓ Branch 0 taken 166319 times.
✓ Branch 1 taken 1392552 times.
|
1558871 | while (this->mjd_frac < 0.0L) |
177 | { | ||
178 | 166319 | this->mjd_frac += 1.0L; | |
179 | 166319 | this->mjd_day--; | |
180 | } | ||
181 | 1392552 | } | |
182 | |||
183 | /// @brief Equal comparison operator (takes double precision into account) | ||
184 | /// @param[in] rhs Right-hand side to compare with | ||
185 | /// @return Comparison result | ||
186 | 7289013 | constexpr bool operator==(const InsTime_MJD& rhs) const | |
187 | { | ||
188 |
2/2✓ Branch 0 taken 7254379 times.
✓ Branch 1 taken 34634 times.
|
7289013 | if (mjd_day == rhs.mjd_day) |
189 | { | ||
190 | 7254379 | auto difference = gcem::abs(mjd_frac - rhs.mjd_frac); | |
191 | 7254385 | return difference <= InsTimeUtil::EPSILON; | |
192 | } | ||
193 | 69454 | if (auto diffDays = mjd_day - rhs.mjd_day; | |
194 |
2/2✓ Branch 1 taken 82 times.
✓ Branch 2 taken 34738 times.
|
34634 | gcem::abs(diffDays) == 1) |
195 | { | ||
196 | 82 | auto difference = 1 + diffDays * (mjd_frac - rhs.mjd_frac); | |
197 | 82 | return difference <= InsTimeUtil::EPSILON; | |
198 | } | ||
199 | 34738 | return false; | |
200 | } | ||
201 | /// @brief Inequal comparison operator (takes double precision into account) | ||
202 | /// @param[in] rhs Right-hand side to compare with | ||
203 | /// @return Comparison result | ||
204 | 240380 | constexpr bool operator!=(const InsTime_MJD& rhs) const | |
205 | { | ||
206 | 240380 | return !(*this == rhs); | |
207 | } | ||
208 | /// @brief Smaller or equal comparison operator (takes double precision into account) | ||
209 | /// @param[in] rhs Right-hand side to compare with | ||
210 | /// @return Comparison result | ||
211 | 20 | constexpr bool operator<=(const InsTime_MJD& rhs) const | |
212 | { | ||
213 |
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; |
214 | } | ||
215 | /// @brief Greater or equal comparison operator (takes double precision into account) | ||
216 | /// @param[in] rhs Right-hand side to compare with | ||
217 | /// @return Comparison result | ||
218 | 8 | constexpr bool operator>=(const InsTime_MJD& rhs) const | |
219 | { | ||
220 |
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; |
221 | } | ||
222 | /// @brief Smaller comparison operator (takes double precision into account) | ||
223 | /// @param[in] rhs Right-hand side to compare with | ||
224 | /// @return Comparison result | ||
225 | 1067174 | constexpr bool operator<(const InsTime_MJD& rhs) const | |
226 | { | ||
227 |
3/4✓ Branch 0 taken 1067386 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 239933 times.
✓ Branch 3 taken 827453 times.
|
1067361 | return (mjd_day < rhs.mjd_day || (mjd_day == rhs.mjd_day && mjd_frac < rhs.mjd_frac)) |
228 |
3/4✓ Branch 0 taken 1067361 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 239127 times.
✓ Branch 4 taken 1084 times.
|
2134535 | && *this != rhs; |
229 | } | ||
230 | /// @brief Greater comparison operator (takes double precision into account) | ||
231 | /// @param[in] rhs Right-hand side to compare with | ||
232 | /// @return Comparison result | ||
233 | 12 | constexpr bool operator>(const InsTime_MJD& rhs) const | |
234 | { | ||
235 | 12 | return !(*this <= rhs); | |
236 | } | ||
237 | |||
238 | /// @brief Converts the object into a readable string | ||
239 | explicit operator std::string() const; | ||
240 | }; | ||
241 | |||
242 | /// Julien Date [UTC] | ||
243 | struct InsTime_JD | ||
244 | { | ||
245 | int32_t jd_day{}; ///< Full days since 1. January −4712 [UTC] | ||
246 | long double jd_frac{}; ///< Decimal fractions of a day of the Julien Date [UTC] | ||
247 | |||
248 | /// @brief Constructor | ||
249 | /// @param[in] jd_day Full days of the Julien Date [UTC] | ||
250 | /// @param[in] jd_frac Decimal fractions of a day of the Julien Date [UTC] | ||
251 | 232388 | constexpr InsTime_JD(int32_t jd_day, long double jd_frac) | |
252 | 232388 | : jd_day(jd_day), jd_frac(jd_frac) | |
253 | { | ||
254 |
2/2✓ Branch 0 taken 10671 times.
✓ Branch 1 taken 221717 times.
|
232388 | if (this->jd_frac >= 1.0L) |
255 | { | ||
256 | 10671 | this->jd_day += static_cast<int32_t>(this->jd_frac); | |
257 | 10671 | this->jd_frac -= static_cast<int32_t>(this->jd_frac); | |
258 | } | ||
259 |
2/2✓ Branch 0 taken 138703 times.
✓ Branch 1 taken 232388 times.
|
371091 | while (this->jd_frac < 0.0L) |
260 | { | ||
261 | 138703 | this->jd_frac += 1.0L; | |
262 | 138703 | this->jd_day--; | |
263 | } | ||
264 | 232388 | } | |
265 | |||
266 | /// @brief Equal comparison operator (takes double precision into account) | ||
267 | /// @param[in] rhs Right-hand side to compare with | ||
268 | /// @return Comparison result | ||
269 | 56 | constexpr bool operator==(const InsTime_JD& rhs) const | |
270 | { | ||
271 |
2/2✓ Branch 0 taken 36 times.
✓ Branch 1 taken 20 times.
|
56 | if (jd_day == rhs.jd_day) |
272 | { | ||
273 | 36 | auto difference = gcem::abs(jd_frac - rhs.jd_frac); | |
274 | 36 | return difference <= InsTimeUtil::EPSILON; | |
275 | } | ||
276 | 40 | if (auto diffDays = jd_day - rhs.jd_day; | |
277 |
1/2✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
|
20 | gcem::abs(diffDays) == 1) |
278 | { | ||
279 | 20 | auto difference = 1 + diffDays * (jd_frac - rhs.jd_frac); | |
280 | 20 | return difference <= InsTimeUtil::EPSILON; | |
281 | } | ||
282 | ✗ | return false; | |
283 | } | ||
284 | /// @brief Inequal comparison operator (takes double precision into account) | ||
285 | /// @param[in] rhs Right-hand side to compare with | ||
286 | /// @return Comparison result | ||
287 | 28 | constexpr bool operator!=(const InsTime_JD& rhs) const | |
288 | { | ||
289 | 28 | return !(*this == rhs); | |
290 | } | ||
291 | /// @brief Smaller or equal comparison operator (takes double precision into account) | ||
292 | /// @param[in] rhs Right-hand side to compare with | ||
293 | /// @return Comparison result | ||
294 | 20 | constexpr bool operator<=(const InsTime_JD& rhs) const | |
295 | { | ||
296 |
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; |
297 | } | ||
298 | /// @brief Greater or equal comparison operator (takes double precision into account) | ||
299 | /// @param[in] rhs Right-hand side to compare with | ||
300 | /// @return Comparison result | ||
301 | 8 | constexpr bool operator>=(const InsTime_JD& rhs) const | |
302 | { | ||
303 |
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; |
304 | } | ||
305 | /// @brief Smaller comparison operator (takes double precision into account) | ||
306 | /// @param[in] rhs Right-hand side to compare with | ||
307 | /// @return Comparison result | ||
308 | 24 | constexpr bool operator<(const InsTime_JD& rhs) const | |
309 | { | ||
310 |
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)) |
311 |
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; |
312 | } | ||
313 | /// @brief Greater comparison operator (takes double precision into account) | ||
314 | /// @param[in] rhs Right-hand side to compare with | ||
315 | /// @return Comparison result | ||
316 | 12 | constexpr bool operator>(const InsTime_JD& rhs) const | |
317 | { | ||
318 | 12 | return !(*this <= rhs); | |
319 | } | ||
320 | |||
321 | /// @brief Converts the object into a readable string | ||
322 | explicit operator std::string() const; | ||
323 | }; | ||
324 | |||
325 | /// GPS week and time of week in GPS standard time [GPST] | ||
326 | struct InsTime_GPSweekTow | ||
327 | { | ||
328 | int32_t gpsCycle{}; ///< Contains GPS cycle in GPS standard time [GPST] | ||
329 | int32_t gpsWeek{}; ///< Contains GPS week in GPS standard time [GPST] | ||
330 | long double tow{}; ///< Contains GPS time of week in seconds in GPS standard time [GPST] | ||
331 | |||
332 | /// @brief Constructor | ||
333 | /// @param[in] gpsCycle GPS cycle in GPS standard time [GPST] | ||
334 | /// @param[in] gpsWeek GPS week in GPS standard time [GPST] | ||
335 | /// @param[in] tow GPS time of week in seconds in GPS standard time [GPST] | ||
336 | 240430 | constexpr InsTime_GPSweekTow(int32_t gpsCycle, int32_t gpsWeek, long double tow) | |
337 | 240430 | : gpsCycle(gpsCycle), gpsWeek(gpsWeek), tow(tow) | |
338 | { | ||
339 |
2/2✓ Branch 0 taken 139342 times.
✓ Branch 1 taken 101088 times.
|
240430 | if (this->tow >= InsTimeUtil::SECONDS_PER_WEEK) |
340 | { | ||
341 | 139342 | this->gpsWeek += static_cast<int32_t>(this->tow / InsTimeUtil::SECONDS_PER_WEEK); | |
342 | 139342 | this->tow = gcem::fmod(this->tow, InsTimeUtil::SECONDS_PER_WEEK); | |
343 | } | ||
344 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 240430 times.
|
240430 | while (this->tow < 0.0L) |
345 | { | ||
346 | ✗ | this->tow += InsTimeUtil::SECONDS_PER_WEEK; | |
347 | ✗ | this->gpsWeek--; | |
348 | } | ||
349 | |||
350 |
2/2✓ Branch 0 taken 210417 times.
✓ Branch 1 taken 30013 times.
|
240430 | if (this->gpsWeek >= InsTimeUtil::WEEKS_PER_GPS_CYCLE) |
351 | { | ||
352 | 210417 | this->gpsCycle += this->gpsWeek / InsTimeUtil::WEEKS_PER_GPS_CYCLE; | |
353 | 210417 | this->gpsWeek %= InsTimeUtil::WEEKS_PER_GPS_CYCLE; | |
354 | } | ||
355 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 240430 times.
|
240430 | while (this->gpsWeek < 0) |
356 | { | ||
357 | ✗ | this->gpsWeek += InsTimeUtil::WEEKS_PER_GPS_CYCLE; | |
358 | ✗ | this->gpsCycle--; | |
359 | } | ||
360 | 240430 | }; | |
361 | |||
362 | /// @brief Equal comparison operator (takes double precision into account) | ||
363 | /// @param[in] rhs Right-hand side to compare with | ||
364 | /// @return Comparison result | ||
365 | 78 | constexpr bool operator==(const InsTime_GPSweekTow& rhs) const | |
366 | { | ||
367 |
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) |
368 | { | ||
369 | 38 | return gcem::abs(tow - rhs.tow) <= InsTimeUtil::EPSILON; | |
370 | } | ||
371 | 80 | if (auto diffWeeks = gpsCycle * InsTimeUtil::WEEKS_PER_GPS_CYCLE + gpsWeek - (rhs.gpsCycle * InsTimeUtil::WEEKS_PER_GPS_CYCLE + rhs.gpsWeek); | |
372 |
2/2✓ Branch 1 taken 26 times.
✓ Branch 2 taken 14 times.
|
40 | gcem::abs(diffWeeks) == 1) |
373 | { | ||
374 | 26 | return gcem::abs(tow + diffWeeks * InsTimeUtil::SECONDS_PER_WEEK - rhs.tow) <= InsTimeUtil::EPSILON; | |
375 | } | ||
376 | 14 | return false; | |
377 | } | ||
378 | /// @brief Inequal comparison operator (takes double precision into account) | ||
379 | /// @param[in] rhs Right-hand side to compare with | ||
380 | /// @return Comparison result | ||
381 | 36 | constexpr bool operator!=(const InsTime_GPSweekTow& rhs) const | |
382 | { | ||
383 | 36 | return !(*this == rhs); | |
384 | } | ||
385 | /// @brief Smaller or equal comparison operator (takes double precision into account) | ||
386 | /// @param[in] rhs Right-hand side to compare with | ||
387 | /// @return Comparison result | ||
388 | 30 | constexpr bool operator<=(const InsTime_GPSweekTow& rhs) const | |
389 | { | ||
390 |
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; |
391 | } | ||
392 | /// @brief Greater or equal comparison operator (takes double precision into account) | ||
393 | /// @param[in] rhs Right-hand side to compare with | ||
394 | /// @return Comparison result | ||
395 | 12 | constexpr bool operator>=(const InsTime_GPSweekTow& rhs) const | |
396 | { | ||
397 |
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; |
398 | } | ||
399 | /// @brief Smaller comparison operator (takes double precision into account) | ||
400 | /// @param[in] rhs Right-hand side to compare with | ||
401 | /// @return Comparison result | ||
402 | 36 | constexpr bool operator<(const InsTime_GPSweekTow& rhs) const | |
403 | { | ||
404 | 36 | return (gpsCycle < rhs.gpsCycle | |
405 |
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) |
406 |
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)) |
407 |
3/4✓ Branch 0 taken 28 times.
✓ Branch 1 taken 8 times.
✓ Branch 3 taken 24 times.
✗ Branch 4 not taken.
|
64 | && *this != rhs; |
408 | } | ||
409 | /// @brief Greater comparison operator (takes double precision into account) | ||
410 | /// @param[in] rhs Right-hand side to compare with | ||
411 | /// @return Comparison result | ||
412 | 18 | constexpr bool operator>(const InsTime_GPSweekTow& rhs) const | |
413 | { | ||
414 | 18 | return !(*this <= rhs); | |
415 | } | ||
416 | |||
417 | /// @brief Converts the object into a readable string | ||
418 | explicit operator std::string() const; | ||
419 | }; | ||
420 | |||
421 | /// Universal Time Coordinated [UTC] | ||
422 | struct InsTime_YMDHMS | ||
423 | { | ||
424 | int32_t year{}; ///< Contains year in Universal Time Coordinated [UTC] | ||
425 | int32_t month{}; ///< Contains month in Universal Time Coordinated [UTC] | ||
426 | int32_t day{}; ///< Contains day in Universal Time Coordinated [UTC] | ||
427 | int32_t hour{}; ///< Contains hour in Universal Time Coordinated [UTC] | ||
428 | int32_t min{}; ///< Contains minute in Universal Time Coordinated [UTC] | ||
429 | long double sec{}; ///< Contains second in Universal Time Coordinated [UTC] | ||
430 | |||
431 | /// @brief Constructor | ||
432 | /// @param[in] year Year in Universal Time Coordinated [UTC] | ||
433 | /// @param[in] month Month in Universal Time Coordinated (1 = January) [UTC] | ||
434 | /// @param[in] day Day in Universal Time Coordinated (1 = first day) [UTC] | ||
435 | /// @param[in] hour Hour in Universal Time Coordinated [UTC] | ||
436 | /// @param[in] min Minute in Universal Time Coordinated [UTC] | ||
437 | /// @param[in] sec Second in Universal Time Coordinated [UTC] | ||
438 | /// @param[in] digits Amount of digits for the seconds to round to | ||
439 | 232492 | constexpr InsTime_YMDHMS(int32_t year, int32_t month, int32_t day, int32_t hour, int32_t min, long double sec, int digits = -1) | |
440 | 232492 | : year(year), month(month), day(day), hour(hour), min(min), sec(sec) | |
441 | { | ||
442 |
2/2✓ Branch 0 taken 2147 times.
✓ Branch 1 taken 230345 times.
|
232492 | if (digits >= 0) { this->sec = math::round(this->sec, static_cast<size_t>(digits)); } |
443 |
2/2✓ Branch 0 taken 52459 times.
✓ Branch 1 taken 180033 times.
|
232492 | if (this->sec >= InsTimeUtil::SECONDS_PER_MINUTE) |
444 | { | ||
445 | 52459 | this->min += static_cast<int32_t>(this->sec / InsTimeUtil::SECONDS_PER_MINUTE); | |
446 | 52459 | this->sec = gcem::fmod(this->sec, InsTimeUtil::SECONDS_PER_MINUTE); | |
447 | } | ||
448 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 232492 times.
|
232492 | while (this->sec < 0.0L) |
449 | { | ||
450 | ✗ | this->sec += InsTimeUtil::SECONDS_PER_MINUTE; | |
451 | ✗ | this->min--; | |
452 | } | ||
453 |
2/2✓ Branch 0 taken 2147 times.
✓ Branch 1 taken 230345 times.
|
232492 | if (digits >= 0) { this->sec = math::round(this->sec, static_cast<size_t>(digits)); } |
454 | |||
455 |
2/2✓ Branch 0 taken 50755 times.
✓ Branch 1 taken 181737 times.
|
232492 | if (this->min >= InsTimeUtil::MINUTES_PER_HOUR) |
456 | { | ||
457 | 50755 | this->hour += this->min / InsTimeUtil::MINUTES_PER_HOUR; | |
458 | 50755 | this->min %= InsTimeUtil::MINUTES_PER_HOUR; | |
459 | } | ||
460 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 232492 times.
|
232492 | while (this->min < 0) |
461 | { | ||
462 | ✗ | this->min += InsTimeUtil::MINUTES_PER_HOUR; | |
463 | ✗ | this->hour--; | |
464 | } | ||
465 | |||
466 |
2/2✓ Branch 0 taken 6409 times.
✓ Branch 1 taken 226083 times.
|
232492 | if (this->hour >= InsTimeUtil::HOURS_PER_DAY) |
467 | { | ||
468 | 6409 | this->day += this->hour / InsTimeUtil::HOURS_PER_DAY; | |
469 | 6409 | this->hour %= InsTimeUtil::HOURS_PER_DAY; | |
470 | } | ||
471 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 232492 times.
|
232492 | while (this->hour < 0) |
472 | { | ||
473 | ✗ | this->hour += InsTimeUtil::HOURS_PER_DAY; | |
474 | ✗ | this->day--; | |
475 | } | ||
476 | |||
477 |
2/2✓ Branch 1 taken 279090 times.
✓ Branch 2 taken 232492 times.
|
511586 | while (this->day >= InsTimeUtil::DAYS_PER_YEAR + static_cast<int32_t>(InsTimeUtil::isLeapYear(this->year))) |
478 | { | ||
479 | 279090 | this->day -= InsTimeUtil::DAYS_PER_YEAR + static_cast<int32_t>(InsTimeUtil::isLeapYear(this->year)); | |
480 | 279094 | this->year++; | |
481 | } | ||
482 | |||
483 |
2/2✓ Branch 1 taken 14 times.
✓ Branch 2 taken 232496 times.
|
232506 | while (this->day > InsTimeUtil::daysInMonth(this->month, this->year)) |
484 | { | ||
485 | 14 | this->day -= InsTimeUtil::daysInMonth(this->month, this->year); | |
486 | 14 | this->month++; | |
487 | } | ||
488 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 232496 times.
|
232498 | while (this->day < 1) |
489 | { | ||
490 | 2 | this->month--; | |
491 | 2 | this->day += InsTimeUtil::daysInMonth(this->month, this->year); | |
492 | } | ||
493 | |||
494 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 232496 times.
|
232502 | while (this->month > InsTimeUtil::MONTHS_PER_YEAR) |
495 | { | ||
496 | 6 | this->month -= InsTimeUtil::MONTHS_PER_YEAR; | |
497 | 6 | this->year++; | |
498 | } | ||
499 |
2/2✓ Branch 0 taken 3006 times.
✓ Branch 1 taken 232496 times.
|
235502 | while (this->month < 1) |
500 | { | ||
501 | 3006 | this->month += InsTimeUtil::MONTHS_PER_YEAR; | |
502 | 3006 | this->year--; | |
503 | } | ||
504 | 232496 | } | |
505 | |||
506 | /// @brief Equal comparison operator (takes double precision into account) | ||
507 | /// @param[in] rhs Right-hand side to compare with | ||
508 | /// @return Comparison result | ||
509 | 162 | constexpr bool operator==(const InsTime_YMDHMS& rhs) const | |
510 | { | ||
511 |
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) |
512 | { | ||
513 | 86 | return gcem::abs(sec - rhs.sec) <= InsTimeUtil::EPSILON; | |
514 | } | ||
515 |
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); |
516 |
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); |
517 |
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) |
518 | { | ||
519 | 6 | return gcem::abs(this_plus.sec - rhs_plus.sec) <= InsTimeUtil::EPSILON; | |
520 | } | ||
521 | 70 | return false; | |
522 | } | ||
523 | /// @brief Inequal comparison operator (takes double precision into account) | ||
524 | /// @param[in] rhs Right-hand side to compare with | ||
525 | /// @return Comparison result | ||
526 | 73 | constexpr bool operator!=(const InsTime_YMDHMS& rhs) const | |
527 | { | ||
528 | 73 | return !(*this == rhs); | |
529 | } | ||
530 | /// @brief Smaller or equal comparison operator (takes double precision into account) | ||
531 | /// @param[in] rhs Right-hand side to compare with | ||
532 | /// @return Comparison result | ||
533 | 62 | constexpr bool operator<=(const InsTime_YMDHMS& rhs) const | |
534 | { | ||
535 |
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; |
536 | } | ||
537 | /// @brief Greater or equal comparison operator (takes double precision into account) | ||
538 | /// @param[in] rhs Right-hand side to compare with | ||
539 | /// @return Comparison result | ||
540 | 25 | constexpr bool operator>=(const InsTime_YMDHMS& rhs) const | |
541 | { | ||
542 |
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; |
543 | } | ||
544 | /// @brief Smaller comparison operator (takes double precision into account) | ||
545 | /// @param[in] rhs Right-hand side to compare with | ||
546 | /// @return Comparison result | ||
547 | 74 | constexpr bool operator<(const InsTime_YMDHMS& rhs) const | |
548 | { | ||
549 | 74 | return (year < rhs.year | |
550 |
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) |
551 |
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) |
552 |
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) |
553 |
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) |
554 |
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)) |
555 |
3/4✓ Branch 0 taken 66 times.
✓ Branch 1 taken 8 times.
✓ Branch 3 taken 48 times.
✗ Branch 4 not taken.
|
140 | && *this != rhs; |
556 | } | ||
557 | /// @brief Greater comparison operator (takes double precision into account) | ||
558 | /// @param[in] rhs Right-hand side to compare with | ||
559 | /// @return Comparison result | ||
560 | 37 | constexpr bool operator>(const InsTime_YMDHMS& rhs) const | |
561 | { | ||
562 | 37 | return !(*this <= rhs); | |
563 | } | ||
564 | |||
565 | /// @brief Converts the object into a readable string | ||
566 | explicit operator std::string() const; | ||
567 | }; | ||
568 | |||
569 | /// GPS year and day of year in GPS standard time [GPST] | ||
570 | struct InsTime_YDoySod | ||
571 | { | ||
572 | int32_t year{}; ///< Contains year in GPS standard time [GPST] | ||
573 | int32_t doy{}; ///< Contains day of year in GPS standard time [GPST] | ||
574 | long double sod{}; ///< Contains second of day in GPS standard time [GPST] | ||
575 | |||
576 | /// @brief Constructor | ||
577 | /// @param[in] year Year in GPS standard time [GPST] | ||
578 | /// @param[in] doy Day of year in GPS standard time [1-365(/366)] | ||
579 | /// @param[in] sod Second of day in GPS standard time [GPST] | ||
580 | 7 | constexpr InsTime_YDoySod(int32_t year, int32_t doy, long double sod) | |
581 | 7 | : year(year), doy(doy), sod(sod) | |
582 | { | ||
583 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
|
7 | if (this->sod >= InsTimeUtil::SECONDS_PER_DAY) |
584 | { | ||
585 | ✗ | this->doy += static_cast<int32_t>(this->sod / InsTimeUtil::SECONDS_PER_DAY); | |
586 | ✗ | this->sod = gcem::fmod(this->sod, InsTimeUtil::SECONDS_PER_DAY); | |
587 | } | ||
588 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
|
7 | while (this->sod < 0) |
589 | { | ||
590 | ✗ | this->sod += InsTimeUtil::SECONDS_PER_DAY; | |
591 | ✗ | this->doy--; | |
592 | } | ||
593 | |||
594 |
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))) |
595 | { | ||
596 | ✗ | this->doy -= InsTimeUtil::DAYS_PER_YEAR + static_cast<int32_t>(InsTimeUtil::isLeapYear(this->year)); | |
597 | ✗ | this->year++; | |
598 | } | ||
599 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
|
7 | while (this->doy < 1) |
600 | { | ||
601 | ✗ | this->doy += InsTimeUtil::DAYS_PER_YEAR + static_cast<int32_t>(InsTimeUtil::isLeapYear(this->year - 1)); | |
602 | ✗ | this->year--; | |
603 | } | ||
604 | 7 | } | |
605 | |||
606 | /// @brief Equal comparison operator (takes double precision into account) | ||
607 | /// @param[in] rhs Right-hand side to compare with | ||
608 | /// @return Comparison result | ||
609 | 78 | constexpr bool operator==(const InsTime_YDoySod& rhs) const | |
610 | { | ||
611 |
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) |
612 | { | ||
613 | 44 | return gcem::abs(sod - rhs.sod) <= InsTimeUtil::EPSILON; | |
614 | } | ||
615 | 68 | if (auto diffDays = year * InsTimeUtil::DAYS_PER_YEAR + doy - (rhs.year * InsTimeUtil::DAYS_PER_YEAR + rhs.doy); | |
616 |
2/2✓ Branch 1 taken 20 times.
✓ Branch 2 taken 14 times.
|
34 | gcem::abs(diffDays) == 1) |
617 | { | ||
618 | 20 | auto difference = gcem::abs(sod + diffDays * InsTimeUtil::SECONDS_PER_DAY - rhs.sod); | |
619 | 20 | return difference <= InsTimeUtil::EPSILON; | |
620 | } | ||
621 | 14 | return false; | |
622 | } | ||
623 | /// @brief Inequal comparison operator (takes double precision into account) | ||
624 | /// @param[in] rhs Right-hand side to compare with | ||
625 | /// @return Comparison result | ||
626 | 36 | constexpr bool operator!=(const InsTime_YDoySod& rhs) const | |
627 | { | ||
628 | 36 | return !(*this == rhs); | |
629 | } | ||
630 | /// @brief Smaller or equal comparison operator (takes double precision into account) | ||
631 | /// @param[in] rhs Right-hand side to compare with | ||
632 | /// @return Comparison result | ||
633 | 30 | constexpr bool operator<=(const InsTime_YDoySod& rhs) const | |
634 | { | ||
635 |
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; |
636 | } | ||
637 | /// @brief Greater or equal comparison operator (takes double precision into account) | ||
638 | /// @param[in] rhs Right-hand side to compare with | ||
639 | /// @return Comparison result | ||
640 | 12 | constexpr bool operator>=(const InsTime_YDoySod& rhs) const | |
641 | { | ||
642 |
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; |
643 | } | ||
644 | /// @brief Smaller comparison operator (takes double precision into account) | ||
645 | /// @param[in] rhs Right-hand side to compare with | ||
646 | /// @return Comparison result | ||
647 | 36 | constexpr bool operator<(const InsTime_YDoySod& rhs) const | |
648 | { | ||
649 | 36 | return (year < rhs.year | |
650 |
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) |
651 |
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)) |
652 |
3/4✓ Branch 0 taken 28 times.
✓ Branch 1 taken 8 times.
✓ Branch 3 taken 24 times.
✗ Branch 4 not taken.
|
64 | && *this != rhs; |
653 | } | ||
654 | /// @brief Greater comparison operator (takes double precision into account) | ||
655 | /// @param[in] rhs Right-hand side to compare with | ||
656 | /// @return Comparison result | ||
657 | 18 | constexpr bool operator>(const InsTime_YDoySod& rhs) const | |
658 | { | ||
659 | 18 | return !(*this <= rhs); | |
660 | } | ||
661 | |||
662 | /// @brief Converts the object into a readable string | ||
663 | explicit operator std::string() const; | ||
664 | }; | ||
665 | |||
666 | /// The class is responsible for all time-related tasks | ||
667 | class InsTime | ||
668 | { | ||
669 | public: | ||
670 | /* ------------------------------ Constructors ------------------------------ */ | ||
671 | |||
672 | /// @brief Default Constructor | ||
673 | 480886 | constexpr InsTime() = default; | |
674 | |||
675 | /// @brief Constructor | ||
676 | /// @param[in] mjd Time in Modified Julien Date | ||
677 | /// @param[in] timesys Time System in which the previous values are given in | ||
678 | 32 | constexpr explicit InsTime(const InsTime_MJD& mjd, TimeSystem timesys = UTC) | |
679 | 32 | : _mjd(mjd) | |
680 | { | ||
681 |
2/4✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 32 times.
✗ Branch 6 not taken.
|
32 | *this -= std::chrono::duration<long double>(differenceToUTC(timesys)); |
682 | 32 | } | |
683 | |||
684 | /// @brief Constructor | ||
685 | /// @param[in] jd Time in Julien Date | ||
686 | /// @param[in] timesys Time System in which the previous values are given in | ||
687 | 192778 | constexpr explicit InsTime(const InsTime_JD& jd, TimeSystem timesys = UTC) | |
688 | 192778 | : _mjd(jd.jd_day - InsTimeUtil::DIFF_MJD_TO_JD_DAYS, jd.jd_frac - InsTimeUtil::DIFF_MJD_TO_JD_FRAC) | |
689 | { | ||
690 |
2/4✓ Branch 1 taken 192772 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 192774 times.
✗ Branch 6 not taken.
|
192779 | *this -= std::chrono::duration<long double>(differenceToUTC(timesys)); |
691 | 192774 | } | |
692 | |||
693 | /// @brief Constructor | ||
694 | /// @param[in] gpsWeekTow Time as week and time of week | ||
695 | /// @param[in] timesys Time System in which the previous values are given in | ||
696 | 101113 | constexpr explicit InsTime(const InsTime_GPSweekTow& gpsWeekTow, TimeSystem timesys = GPST) | |
697 | 101113 | { | |
698 | 101102 | auto mjd_day = static_cast<int32_t>((gpsWeekTow.gpsCycle * InsTimeUtil::WEEKS_PER_GPS_CYCLE + gpsWeekTow.gpsWeek) * InsTimeUtil::DAYS_PER_WEEK | |
699 | 101102 | + gcem::floor(gpsWeekTow.tow / InsTimeUtil::SECONDS_PER_DAY) | |
700 | 101081 | + InsTimeUtil::DIFF_TO_6_1_1980_MJD); | |
701 | 101081 | long double mjd_frac = gcem::fmod(gpsWeekTow.tow, InsTimeUtil::SECONDS_PER_DAY) / InsTimeUtil::SECONDS_PER_DAY; | |
702 | |||
703 | 101095 | _mjd = InsTime_MJD(mjd_day, mjd_frac); | |
704 | |||
705 |
2/4✓ Branch 1 taken 101075 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 101054 times.
✗ Branch 6 not taken.
|
101095 | *this -= std::chrono::duration<long double>(differenceToUTC(timesys)); |
706 | 101054 | } | |
707 | |||
708 | /// @brief Constructor | ||
709 | /// @param[in] yearMonthDayHMS Time in Universal Time Coordinated | ||
710 | /// @param[in] timesys Time System in which the previous values are given in | ||
711 | 192763 | constexpr explicit InsTime(const InsTime_YMDHMS& yearMonthDayHMS, TimeSystem timesys = UTC) | |
712 | 192763 | { | |
713 | 192748 | auto a = static_cast<int32_t>((14 - yearMonthDayHMS.month) / static_cast<double>(InsTimeUtil::MONTHS_PER_YEAR)); | |
714 | 192748 | int32_t y = yearMonthDayHMS.year + 4800 - a; | |
715 | 192748 | int32_t m = yearMonthDayHMS.month + InsTimeUtil::MONTHS_PER_YEAR * a - 3; | |
716 | |||
717 | 192748 | auto jd_day = static_cast<int32_t>(yearMonthDayHMS.day | |
718 | 192748 | + gcem::floor((153.0 * static_cast<double>(m) + 2.0) / 5.0) | |
719 | 192747 | + y * InsTimeUtil::DAYS_PER_YEAR | |
720 | 192747 | + gcem::floor(static_cast<double>(y) / 4.0) | |
721 | 192753 | - gcem::floor(static_cast<double>(y) / 100.0) | |
722 | 192761 | + gcem::floor(static_cast<double>(y) / 400.0) | |
723 | 192761 | - 32045); | |
724 | 192761 | auto jd_frac = (yearMonthDayHMS.sec | |
725 | 192761 | + static_cast<long double>(yearMonthDayHMS.min) * InsTimeUtil::SECONDS_PER_MINUTE | |
726 | 192761 | + static_cast<long double>(yearMonthDayHMS.hour - 12.0) * InsTimeUtil::SECONDS_PER_HOUR) | |
727 | / InsTimeUtil::SECONDS_PER_DAY; | ||
728 | |||
729 |
2/4✓ Branch 3 taken 192751 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 192756 times.
✗ Branch 8 not taken.
|
192761 | _mjd = InsTime(InsTime_JD(jd_day, jd_frac)).toMJD(); |
730 | |||
731 |
2/4✓ Branch 1 taken 192763 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 192761 times.
✗ Branch 6 not taken.
|
192756 | *this -= std::chrono::duration<long double>(differenceToUTC(timesys)); |
732 | 192761 | } | |
733 | |||
734 | /// @brief Constructor | ||
735 | /// @param[in] yearDoySod Time as Year, day of year and seconds of day | ||
736 | /// @param[in] timesys Time System in which the previous values are given in | ||
737 | 28 | constexpr explicit InsTime(const InsTime_YDoySod& yearDoySod, TimeSystem timesys = UTC) | |
738 | 28 | { | |
739 | 28 | auto year = yearDoySod.year; | |
740 | 28 | auto doy = yearDoySod.doy; | |
741 | 28 | auto sod = yearDoySod.sod; | |
742 | |||
743 | 28 | int32_t month = 1; | |
744 |
2/2✓ Branch 1 taken 34 times.
✓ Branch 2 taken 28 times.
|
62 | while (doy > InsTimeUtil::daysInMonth(month, year)) |
745 | { | ||
746 | 34 | doy -= InsTimeUtil::daysInMonth(month, year); | |
747 | 34 | month++; | |
748 | } | ||
749 | |||
750 |
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(); |
751 | |||
752 |
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)); |
753 | 28 | } | |
754 | |||
755 | /// @brief Constructor | ||
756 | /// @param[in] gpsCycle GPS cycle in GPS standard time | ||
757 | /// @param[in] gpsWeek GPS week in GPS standard time | ||
758 | /// @param[in] tow GPS time of week in GPS standard time | ||
759 | /// @param[in] timesys Time System in which the previous values are given in | ||
760 | 72591 | constexpr InsTime(int32_t gpsCycle, int32_t gpsWeek, long double tow, TimeSystem timesys = GPST) | |
761 |
1/2✓ Branch 2 taken 72592 times.
✗ Branch 3 not taken.
|
72591 | : InsTime(InsTime_GPSweekTow(gpsCycle, gpsWeek, tow), timesys) {} |
762 | |||
763 | /// @brief Constructor | ||
764 | /// @param[in] year Year | ||
765 | /// @param[in] month Month (1 = January) | ||
766 | /// @param[in] day Day (1 = first day) | ||
767 | /// @param[in] hour Hour | ||
768 | /// @param[in] min Minute | ||
769 | /// @param[in] sec Second | ||
770 | /// @param[in] timesys Time System in which the previous values are given in | ||
771 | 192684 | constexpr InsTime(int32_t year, int32_t month, int32_t day, int32_t hour, int32_t min, long double sec, TimeSystem timesys = UTC) | |
772 |
2/4✓ Branch 1 taken 192685 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 192694 times.
✗ Branch 5 not taken.
|
192684 | : InsTime(InsTime_YMDHMS(year, month, day, hour, min, sec), timesys) {} |
773 | |||
774 | /// @brief Destructor | ||
775 | ~InsTime() = default; | ||
776 | /// @brief Copy constructor | ||
777 | constexpr InsTime(const InsTime&) = default; | ||
778 | /// @brief Move constructor | ||
779 | constexpr InsTime(InsTime&&) = default; | ||
780 | /// @brief Copy assignment operator | ||
781 | constexpr InsTime& operator=(const InsTime&) = default; | ||
782 | /// @brief Move assignment operator | ||
783 | constexpr InsTime& operator=(InsTime&&) = default; | ||
784 | |||
785 | /* ------------------------ Transformation functions ------------------------ */ | ||
786 | |||
787 | /// @brief Converts this time object into a different format | ||
788 | /// @param timesys Time System in which the time should be given | ||
789 | /// @return InsTime_MJD structure of the this object | ||
790 | 236661 | [[nodiscard]] constexpr InsTime_MJD toMJD(TimeSystem timesys = UTC) const | |
791 | { | ||
792 | 236661 | long double mjdFrac = _mjd.mjd_frac + static_cast<long double>(differenceToUTC(timesys)) / static_cast<long double>(InsTimeUtil::SECONDS_PER_DAY); | |
793 | 236669 | return { _mjd.mjd_day, mjdFrac }; | |
794 | } | ||
795 | |||
796 | /// @brief Converts this time object into a different format | ||
797 | /// @param timesys Time System in which the time should be given | ||
798 | /// @return InsTime_JD structure of the this object | ||
799 | 39626 | [[nodiscard]] constexpr InsTime_JD toJD(TimeSystem timesys = UTC) const | |
800 | { | ||
801 | 39626 | auto jd_day = _mjd.mjd_day + InsTimeUtil::DIFF_MJD_TO_JD_DAYS; | |
802 | 39626 | auto jd_frac = _mjd.mjd_frac + InsTimeUtil::DIFF_MJD_TO_JD_FRAC; | |
803 | |||
804 | 39626 | jd_frac += static_cast<long double>(differenceToUTC(timesys)) / static_cast<long double>(InsTimeUtil::SECONDS_PER_DAY); | |
805 | |||
806 | 39626 | return { jd_day, jd_frac }; | |
807 | } | ||
808 | |||
809 | /// @brief Converts this time object into a different format | ||
810 | /// @param timesys Time System in which the time should be given | ||
811 | /// @return InsTime_GPSweekTow structure of the this object | ||
812 | 139341 | [[nodiscard]] constexpr InsTime_GPSweekTow toGPSweekTow(TimeSystem timesys = GPST) const | |
813 | { | ||
814 | 139341 | InsTime_MJD mjd_leap = _mjd; | |
815 | // Convert from UTC to intended time system | ||
816 |
1/2✓ Branch 1 taken 139342 times.
✗ Branch 2 not taken.
|
139341 | mjd_leap.mjd_frac += static_cast<long double>(differenceToUTC(timesys)) / static_cast<long double>(InsTimeUtil::SECONDS_PER_DAY); |
817 | |||
818 | // Put everything in the time of week, as it gets splitted in InsTime_GPSweekTow constructor | ||
819 | 139342 | auto tow = static_cast<long double>((mjd_leap.mjd_day - InsTimeUtil::DIFF_TO_6_1_1980_MJD)) * InsTimeUtil::SECONDS_PER_DAY | |
820 | 139342 | + mjd_leap.mjd_frac * InsTimeUtil::SECONDS_PER_DAY; | |
821 | |||
822 | 278684 | return { 0, 0, tow }; | |
823 | } | ||
824 | |||
825 | /// @brief Converts this time object into a different format | ||
826 | /// @param timesys Time System in which the time should be given | ||
827 | /// @param digits Amount of digits for the seconds to round to | ||
828 | /// @return InsTime_YMDHMS structure of the this object | ||
829 | 39623 | [[nodiscard]] constexpr InsTime_YMDHMS toYMDHMS(TimeSystem timesys = UTC, int digits = -1) const | |
830 | { | ||
831 | // transform MJD to JD | ||
832 |
1/2✓ Branch 2 taken 39623 times.
✗ Branch 3 not taken.
|
39623 | InsTime_JD jd = toJD(); |
833 | 39623 | jd.jd_frac = jd.jd_frac + 0.5L; | |
834 |
1/2✓ Branch 1 taken 39623 times.
✗ Branch 2 not taken.
|
39623 | jd.jd_frac += static_cast<long double>(differenceToUTC(timesys)) / static_cast<long double>(InsTimeUtil::SECONDS_PER_DAY); |
835 |
2/2✓ Branch 0 taken 28981 times.
✓ Branch 1 taken 10642 times.
|
39623 | if (jd.jd_frac >= 1.0L) |
836 | { | ||
837 | 28981 | jd.jd_day += static_cast<int32_t>(jd.jd_frac); | |
838 | 28981 | jd.jd_frac -= gcem::floor(jd.jd_frac); | |
839 | } | ||
840 | // transform JD to YMDHMS | ||
841 | 39623 | double a = 32044.0 + jd.jd_day; | |
842 | 39623 | double b = gcem::floor((4.0 * a + 3.0) / 146097.0); | |
843 | 39623 | double c = a - gcem::floor((b * 146097.0) / 4.0); | |
844 | |||
845 | 39623 | double d = gcem::floor((4.0 * c + 3.0) / 1461.0); | |
846 | 39623 | double e = c - gcem::floor((1461.0 * d) / 4.0); | |
847 | 39623 | double m = gcem::floor((5.0 * e + 2.0) / 153.0); | |
848 | |||
849 | 39623 | auto day = static_cast<uint16_t>(e - gcem::floor((153.0 * m + 2.0) / 5.0) + 1); | |
850 | 39623 | auto month = static_cast<uint16_t>(m + 3 - 12 * gcem::floor(m / 10.0)); | |
851 | 39623 | auto year = static_cast<uint16_t>(b * 100 + d - 4800.0 + gcem::floor(m / 10.0)); | |
852 | |||
853 | 39623 | long double sec = jd.jd_frac * InsTimeUtil::SECONDS_PER_DAY; | |
854 | |||
855 |
1/2✓ Branch 1 taken 39623 times.
✗ Branch 2 not taken.
|
79246 | return { year, month, day, 0, 0, sec, digits }; |
856 | } | ||
857 | |||
858 | /// @brief Converts this time object into a different format | ||
859 | /// @param timesys Time System in which the time should be given | ||
860 | /// @return InsTime_YDoySod structure of the this object | ||
861 | 4 | [[nodiscard]] constexpr InsTime_YDoySod toYDoySod(TimeSystem timesys = UTC) const | |
862 | { | ||
863 |
1/2✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
4 | InsTime_YMDHMS yearMonthDayHMS = toYMDHMS(); |
864 | |||
865 | 4 | auto year = yearMonthDayHMS.year; | |
866 | 4 | long double sod = static_cast<long double>(yearMonthDayHMS.hour * InsTimeUtil::SECONDS_PER_HOUR | |
867 | 4 | + yearMonthDayHMS.min * InsTimeUtil::SECONDS_PER_MINUTE) | |
868 | 4 | + yearMonthDayHMS.sec | |
869 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | + static_cast<long double>(differenceToUTC(timesys)); |
870 | |||
871 | 4 | int32_t doy = 0; | |
872 |
2/2✓ Branch 0 taken 14 times.
✓ Branch 1 taken 4 times.
|
18 | for (int32_t i = 1; i < yearMonthDayHMS.month; i++) |
873 | { | ||
874 | 14 | doy += InsTimeUtil::daysInMonth(i, year); | |
875 | } | ||
876 | 4 | doy += yearMonthDayHMS.day; | |
877 | |||
878 | 8 | return { year, doy, sod }; | |
879 | } | ||
880 | |||
881 | /// @brief Returns the current time rounded/cutted to a full day (changes time to 0:0:0h UTC of current day) | ||
882 | /// @return The rounded/cutted time object | ||
883 | [[nodiscard]] constexpr InsTime toFullDay() const | ||
884 | { | ||
885 | return InsTime(InsTime_MJD(_mjd.mjd_day, 0.0L)); | ||
886 | } | ||
887 | |||
888 | /// @brief Converts this time object into a UNIX timestamp in [s] | ||
889 | /// @attention Do not pass `long double` to the LOG_... functions, it can loop indefinitely | ||
890 | 4 | [[nodiscard]] constexpr long double toUnixTime() const | |
891 | { | ||
892 | 4 | return static_cast<long double>((_mjd.mjd_day - InsTimeUtil::DIFF_TO_1_1_1970_MJD) * InsTimeUtil::SECONDS_PER_DAY) | |
893 | 4 | + _mjd.mjd_frac * InsTimeUtil::SECONDS_PER_DAY; | |
894 | } | ||
895 | |||
896 | /* ----------------------------- Leap functions ----------------------------- */ | ||
897 | |||
898 | /// @brief Returns the current number of leap seconds (offset GPST to UTC) | ||
899 | /// @return Number of leap seconds | ||
900 | 466020 | [[nodiscard]] constexpr uint16_t leapGps2UTC() const | |
901 | { | ||
902 | 466020 | return leapGps2UTC(_mjd); | |
903 | } | ||
904 | |||
905 | /// @brief Returns the number of leap seconds (offset GPST to UTC) for the provided InsTime object | ||
906 | /// @param[in] insTime Time point | ||
907 | /// @return Number of leap seconds | ||
908 | 7 | static constexpr uint16_t leapGps2UTC(const InsTime& insTime) | |
909 | { | ||
910 | 7 | return leapGps2UTC(insTime._mjd); | |
911 | } | ||
912 | |||
913 | /// @brief Returns the number of leap seconds (offset GPST to UTC) for the provided InsTime_GPSweekTow object | ||
914 | /// @param[in] gpsWeekTow Time point | ||
915 | /// @return Number of leap seconds | ||
916 | 1 | static constexpr uint16_t leapGps2UTC(const InsTime_GPSweekTow& gpsWeekTow) | |
917 | { | ||
918 |
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()); |
919 | } | ||
920 | |||
921 | /// @brief Returns the number of leap seconds (offset GPST to UTC) for the provided InsTime_YDoySod object | ||
922 | /// @param[in] yearDoySod Time point | ||
923 | /// @return Number of leap seconds | ||
924 | 1 | static constexpr uint16_t leapGps2UTC(const InsTime_YDoySod& yearDoySod) | |
925 | { | ||
926 |
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()); |
927 | } | ||
928 | |||
929 | /// @brief Returns the number of leap seconds (offset GPST to UTC) for the provided InsTime_YMDHMS object | ||
930 | /// @param[in] yearMonthDayHMS Time point | ||
931 | /// @return Number of leap seconds | ||
932 | 1 | static constexpr uint16_t leapGps2UTC(const InsTime_YMDHMS& yearMonthDayHMS) | |
933 | { | ||
934 |
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()); |
935 | } | ||
936 | |||
937 | /// @brief Returns the number of leap seconds (offset GPST to UTC) for the provided InsTime_JD object | ||
938 | /// @param[in] jd Time point | ||
939 | /// @return Number of leap seconds | ||
940 | 1 | static constexpr uint16_t leapGps2UTC(const InsTime_JD& jd) | |
941 | { | ||
942 |
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()); |
943 | } | ||
944 | |||
945 | /// @brief Returns the number of leap seconds (offset GPST to UTC) for the provided InsTime_MJD object | ||
946 | /// @param[in] mjd_in Time point | ||
947 | /// @return Number of leap seconds | ||
948 | 466026 | static constexpr uint16_t leapGps2UTC(const InsTime_MJD& mjd_in) | |
949 | { | ||
950 | 466026 | 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); | |
951 | } | ||
952 | |||
953 | /// @brief Checks if the current time is a leap year | ||
954 | /// @return True if the current time is a leap year, false otherwise | ||
955 | 1 | [[nodiscard]] constexpr bool isLeapYear() const | |
956 | { | ||
957 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | return InsTimeUtil::isLeapYear(toYMDHMS().year); |
958 | } | ||
959 | |||
960 | /* --------------------- Comparison operator overloading -------------------- */ | ||
961 | |||
962 | /// @brief Equal comparison operator (takes double precision into account) | ||
963 | /// @param[in] rhs Right-hand side to compare with | ||
964 | /// @return Comparison result | ||
965 | 7049138 | constexpr bool operator==(const InsTime& rhs) const { return _mjd == rhs._mjd; } | |
966 | /// @brief Inequal comparison operator (takes double precision into account) | ||
967 | /// @param[in] rhs Right-hand side to compare with | ||
968 | /// @return Comparison result | ||
969 | 50047 | constexpr bool operator!=(const InsTime& rhs) const { return !(*this == rhs); } | |
970 | /// @brief Smaller or equal comparison operator (takes double precision into account) | ||
971 | /// @param[in] rhs Right-hand side to compare with | ||
972 | /// @return Comparison result | ||
973 |
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; } |
974 | /// @brief Greater or equal comparison operator (takes double precision into account) | ||
975 | /// @param[in] rhs Right-hand side to compare with | ||
976 | /// @return Comparison result | ||
977 |
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; } |
978 | /// @brief Smaller comparison operator (takes double precision into account) | ||
979 | /// @param[in] rhs Right-hand side to compare with | ||
980 | /// @return Comparison result | ||
981 | 1067570 | constexpr bool operator<(const InsTime& rhs) const { return _mjd < rhs._mjd; } | |
982 | /// @brief Greater comparison operator (takes double precision into account) | ||
983 | /// @param[in] rhs Right-hand side to compare with | ||
984 | /// @return Comparison result | ||
985 | 27568 | constexpr bool operator>(const InsTime& rhs) const { return !(*this <= rhs); } | |
986 | |||
987 | /* --------------------- Arithmetic operator overloading -------------------- */ | ||
988 | |||
989 | /// @brief Substracts 2 points in time | ||
990 | /// @param[in] lhs The left hand side time point | ||
991 | /// @param[in] rhs The right hand side time point | ||
992 | /// @return Time difference in [seconds] | ||
993 | 1645875 | constexpr friend std::chrono::duration<long double> operator-(const InsTime& lhs, const InsTime& rhs) | |
994 | { | ||
995 | 1645875 | auto diffDays = lhs._mjd.mjd_day - rhs._mjd.mjd_day; | |
996 | 1645875 | auto diffFrac = lhs._mjd.mjd_frac - rhs._mjd.mjd_frac; | |
997 | 1645875 | long double diffSec = (diffFrac + static_cast<long double>(diffDays)) * InsTimeUtil::SECONDS_PER_DAY; | |
998 | 1645875 | return std::chrono::duration<long double>(diffSec); | |
999 | } | ||
1000 | |||
1001 | /// @brief Adds a duration to this time point | ||
1002 | /// @param[in] duration The duration to add | ||
1003 | /// @return Reference to this object | ||
1004 | 201715 | constexpr InsTime& operator+=(const std::chrono::duration<long double>& duration) | |
1005 | { | ||
1006 |
1/2✓ Branch 1 taken 201721 times.
✗ Branch 2 not taken.
|
201715 | auto duration_mjd_frac = std::chrono::duration<long double, std::ratio<InsTimeUtil::SECONDS_PER_DAY>>(duration).count(); |
1007 | 403442 | this->_mjd = InsTime_MJD(this->_mjd.mjd_day, | |
1008 | 201716 | this->_mjd.mjd_frac + duration_mjd_frac); | |
1009 | 201726 | return *this; | |
1010 | } | ||
1011 | |||
1012 | /// @brief Substracts a duration to this time point | ||
1013 | /// @param[in] duration The duration to substract | ||
1014 | /// @return Reference to this object | ||
1015 | 660315 | constexpr InsTime& operator-=(const std::chrono::duration<long double>& duration) | |
1016 | { | ||
1017 |
1/2✓ Branch 1 taken 660281 times.
✗ Branch 2 not taken.
|
660315 | auto duration_mjd_frac = std::chrono::duration<long double, std::ratio<InsTimeUtil::SECONDS_PER_DAY>>(duration).count(); |
1018 | 1320574 | this->_mjd = InsTime_MJD(this->_mjd.mjd_day, | |
1019 | 660260 | this->_mjd.mjd_frac - duration_mjd_frac); | |
1020 | 660314 | return *this; | |
1021 | } | ||
1022 | |||
1023 | /// @brief Adds a duration to a time point | ||
1024 | /// @param[in] time The left hand side time point | ||
1025 | /// @param[in] duration The right hand side duration | ||
1026 | /// @return Time point with the added duration | ||
1027 | 200747 | constexpr friend InsTime operator+(const InsTime& time, const std::chrono::duration<long double>& duration) | |
1028 | { | ||
1029 |
1/2✓ Branch 1 taken 200759 times.
✗ Branch 2 not taken.
|
200747 | return InsTime(time) += duration; |
1030 | } | ||
1031 | |||
1032 | /// @brief Substracts a duration from a time point | ||
1033 | /// @param[in] time The left hand side time point | ||
1034 | /// @param[in] duration The right hand side duration | ||
1035 | /// @return Time point with the substracted duration | ||
1036 | 173642 | constexpr friend InsTime operator-(const InsTime& time, const std::chrono::duration<long double>& duration) | |
1037 | { | ||
1038 |
1/2✓ Branch 1 taken 173642 times.
✗ Branch 2 not taken.
|
173642 | return InsTime(time) -= duration; |
1039 | } | ||
1040 | |||
1041 | /* ---------------------------- Utility Functions --------------------------- */ | ||
1042 | |||
1043 | /// @brief Converts the object into a readable string | ||
1044 | explicit operator std::string() const; | ||
1045 | |||
1046 | /// @brief Checks if the Time object has a value | ||
1047 | 2598259 | [[nodiscard]] constexpr bool empty() const | |
1048 | { | ||
1049 |
4/4✓ Branch 0 taken 481056 times.
✓ Branch 1 taken 2117203 times.
✓ Branch 2 taken 481011 times.
✓ Branch 3 taken 45 times.
|
2598259 | return _mjd.mjd_day == 0 && _mjd.mjd_frac == 0.0L; |
1050 | } | ||
1051 | |||
1052 | /// @brief Resets the InsTime object | ||
1053 | 220417 | void reset() | |
1054 | { | ||
1055 | 220417 | _mjd.mjd_day = 0; | |
1056 | 220417 | _mjd.mjd_frac = 0.0L; | |
1057 | 220417 | } | |
1058 | |||
1059 | /// @brief Adds the difference [seconds] between toe (OBRIT-0 last element) and toc (ORBIT-0 first element) to the current time | ||
1060 | /// (Changes time, so that it corresponds to the time of GLONASS ORBIT last element) | ||
1061 | /// @param[in] UTC_sec Seconds in UTC time | ||
1062 | void MakeTimeFromGloOrbit(double UTC_sec) | ||
1063 | { | ||
1064 | auto ymdhms = toYMDHMS(); | ||
1065 | // difference between toe (OBRIT-0 last element) and toc (ORBIT-0 first element) in seconds | ||
1066 | long double diff = gcem::fmod(static_cast<long double>(UTC_sec), InsTimeUtil::SECONDS_PER_DAY) | ||
1067 | - (ymdhms.hour * InsTimeUtil::SECONDS_PER_HOUR | ||
1068 | + ymdhms.min * InsTimeUtil::SECONDS_PER_MINUTE | ||
1069 | + ymdhms.sec); | ||
1070 | // std::cout << "orbit diff " << diff << "\n"; | ||
1071 | *this += std::chrono::duration<long double>(diff); | ||
1072 | } | ||
1073 | |||
1074 | /// @brief Returns the time difference in [s] of a time system and UTC | ||
1075 | /// @param[in] timesys Time system to get the difference from UTC | ||
1076 | 942034 | [[nodiscard]] constexpr int differenceToUTC(TimeSystem timesys) const | |
1077 | { | ||
1078 |
7/8✓ Branch 1 taken 398748 times.
✓ Branch 2 taken 17 times.
✓ Branch 3 taken 22882 times.
✓ Branch 4 taken 2172 times.
✓ Branch 5 taken 54 times.
✓ Branch 6 taken 20160 times.
✓ Branch 7 taken 497984 times.
✗ Branch 8 not taken.
|
942034 | switch (TimeSystem_(timesys)) |
1079 | { | ||
1080 | 398748 | case GPST: // = GPS Time (UTC + leap_seconds) | |
1081 | 398748 | return this->leapGps2UTC(); | |
1082 | 17 | case GLNT: // = GLONASS Time (UTC+ 3h) | |
1083 | 17 | return 3 * InsTimeUtil::SECONDS_PER_HOUR; | |
1084 | 22882 | case GST: // = GALILEO Time (~ GPS) (UTC = GST - 18) is synchronized with TAI with a nominal offset below 50 ns | |
1085 | 22882 | return this->leapGps2UTC(); | |
1086 | 2172 | case QZSST: | |
1087 | 2172 | return this->leapGps2UTC(); // TODO citation for synchronization accuracy | |
1088 | 54 | case IRNSST: | |
1089 | 54 | return this->leapGps2UTC(); // TODO citation for synchronization accuracy | |
1090 | 20160 | case BDT: // = BeiDou Time (UTC) is synchronized with UTC within 100 ns< | |
1091 | 20160 | return this->leapGps2UTC() - 14; | |
1092 | 497984 | case UTC: | |
1093 | case TimeSys_None: | ||
1094 | 497984 | return 0; | |
1095 | } | ||
1096 | ✗ | return 0; | |
1097 | } | ||
1098 | |||
1099 | private: | ||
1100 | /// @brief Modified Julien Date of this InsTime object | ||
1101 | InsTime_MJD _mjd; | ||
1102 | }; | ||
1103 | |||
1104 | /// @brief Stream insertion operator overload | ||
1105 | /// @param[in, out] os Output stream object to stream the time into | ||
1106 | /// @param[in] mjd Object to print | ||
1107 | /// @return Returns the output stream object in order to chain stream insertions | ||
1108 | std::ostream& operator<<(std::ostream& os, const InsTime_MJD& mjd); | ||
1109 | /// @brief Stream insertion operator overload | ||
1110 | /// @param[in, out] os Output stream object to stream the time into | ||
1111 | /// @param[in] jd Object to print | ||
1112 | /// @return Returns the output stream object in order to chain stream insertions | ||
1113 | std::ostream& operator<<(std::ostream& os, const InsTime_JD& jd); | ||
1114 | /// @brief Stream insertion operator overload | ||
1115 | /// @param[in, out] os Output stream object to stream the time into | ||
1116 | /// @param[in] gpsWeekTow Object to print | ||
1117 | /// @return Returns the output stream object in order to chain stream insertions | ||
1118 | std::ostream& operator<<(std::ostream& os, const InsTime_GPSweekTow& gpsWeekTow); | ||
1119 | /// @brief Stream insertion operator overload | ||
1120 | /// @param[in, out] os Output stream object to stream the time into | ||
1121 | /// @param[in] ymdhms Object to print | ||
1122 | /// @return Returns the output stream object in order to chain stream insertions | ||
1123 | std::ostream& operator<<(std::ostream& os, const InsTime_YMDHMS& ymdhms); | ||
1124 | /// @brief Stream insertion operator overload | ||
1125 | /// @param[in, out] os Output stream object to stream the time into | ||
1126 | /// @param[in] yDoySod Object to print | ||
1127 | /// @return Returns the output stream object in order to chain stream insertions | ||
1128 | std::ostream& operator<<(std::ostream& os, const InsTime_YDoySod& yDoySod); | ||
1129 | /// @brief Stream insertion operator overload | ||
1130 | /// @param[in, out] os Output stream object to stream the time into | ||
1131 | /// @param[in] insTime Object to print | ||
1132 | /// @return Returns the output stream object in order to chain stream insertions | ||
1133 | std::ostream& operator<<(std::ostream& os, const InsTime& insTime); | ||
1134 | |||
1135 | /// @brief Converts the provided InsTime into a json object | ||
1136 | /// @param[out] j Return Json object | ||
1137 | /// @param[in] insTime Time to convert | ||
1138 | void to_json(json& j, const InsTime& insTime); | ||
1139 | /// @brief Converts the provided json object into an InsTime | ||
1140 | /// @param[in] j Json object with the time values | ||
1141 | /// @param[out] insTime Time to return | ||
1142 | void from_json(const json& j, InsTime& insTime); | ||
1143 | |||
1144 | } // namespace NAV | ||
1145 | |||
1146 | namespace std | ||
1147 | { | ||
1148 | /// @brief Hash function for InsTime (needed for unordered_map) | ||
1149 | template<> | ||
1150 | struct hash<NAV::InsTime> | ||
1151 | { | ||
1152 | /// @brief Hash function for InsTime | ||
1153 | /// @param[in] t Time | ||
1154 | std::size_t operator()(const NAV::InsTime& t) const | ||
1155 | { | ||
1156 | auto hash1 = std::hash<int32_t>{}(t.toMJD().mjd_day); | ||
1157 | auto hash2 = std::hash<long double>{}(t.toMJD().mjd_frac); | ||
1158 | |||
1159 | return hash1 | (hash2 << 32); | ||
1160 | } | ||
1161 | }; | ||
1162 | } // namespace std | ||
1163 | |||
1164 | #ifndef DOXYGEN_IGNORE | ||
1165 | |||
1166 | /// @brief Formatter | ||
1167 | template<> | ||
1168 | struct fmt::formatter<NAV::InsTime_MJD> : fmt::formatter<std::string> | ||
1169 | { | ||
1170 | /// @brief Defines how to format this structs | ||
1171 | /// @param[in] mjd Struct to format | ||
1172 | /// @param[in, out] ctx Format context | ||
1173 | /// @return Output iterator | ||
1174 | template<typename FormatContext> | ||
1175 | ✗ | auto format(const NAV::InsTime_MJD& mjd, FormatContext& ctx) const | |
1176 | { | ||
1177 | ✗ | return fmt::format_to(ctx.out(), "day={}, frac={}", mjd.mjd_day, static_cast<double>(mjd.mjd_frac)); | |
1178 | } | ||
1179 | }; | ||
1180 | /// @brief Formatter | ||
1181 | template<> | ||
1182 | struct fmt::formatter<NAV::InsTime_JD> : fmt::formatter<std::string> | ||
1183 | { | ||
1184 | /// @brief Defines how to format this structs | ||
1185 | /// @param[in] jd Struct to format | ||
1186 | /// @param[in, out] ctx Format context | ||
1187 | /// @return Output iterator | ||
1188 | template<typename FormatContext> | ||
1189 | ✗ | auto format(const NAV::InsTime_JD& jd, FormatContext& ctx) const | |
1190 | { | ||
1191 | ✗ | return fmt::format_to(ctx.out(), "day={}, frac={}", jd.jd_day, static_cast<double>(jd.jd_frac)); | |
1192 | } | ||
1193 | }; | ||
1194 | /// @brief Formatter | ||
1195 | template<> | ||
1196 | struct fmt::formatter<NAV::InsTime_GPSweekTow> : fmt::formatter<std::string> | ||
1197 | { | ||
1198 | /// @brief Defines how to format this structs | ||
1199 | /// @param[in] gpsWeekTow Struct to format | ||
1200 | /// @param[in, out] ctx Format context | ||
1201 | /// @return Output iterator | ||
1202 | template<typename FormatContext> | ||
1203 | 19560 | auto format(const NAV::InsTime_GPSweekTow& gpsWeekTow, FormatContext& ctx) const | |
1204 | { | ||
1205 | 39120 | return fmt::format_to(ctx.out(), "cycle={}, week={}, tow={}", | |
1206 | 39120 | gpsWeekTow.gpsCycle, gpsWeekTow.gpsWeek, static_cast<double>(gpsWeekTow.tow)); | |
1207 | } | ||
1208 | }; | ||
1209 | /// @brief Formatter | ||
1210 | template<> | ||
1211 | struct fmt::formatter<NAV::InsTime_YMDHMS> : fmt::formatter<std::string> | ||
1212 | { | ||
1213 | /// @brief Defines how to format this structs | ||
1214 | /// @param[in] ymdhms Struct to format | ||
1215 | /// @param[in, out] ctx Format context | ||
1216 | /// @return Output iterator | ||
1217 | template<typename FormatContext> | ||
1218 | 37449 | auto format(const NAV::InsTime_YMDHMS& ymdhms, FormatContext& ctx) const | |
1219 | { | ||
1220 | 74898 | return fmt::format_to(ctx.out(), "{}-{}-{} {}:{}:{:.6g}", | |
1221 | 37449 | ymdhms.year, ymdhms.month, ymdhms.day, | |
1222 | 74898 | ymdhms.hour, ymdhms.min, static_cast<double>(ymdhms.sec)); | |
1223 | } | ||
1224 | }; | ||
1225 | /// @brief Formatter | ||
1226 | template<> | ||
1227 | struct fmt::formatter<NAV::InsTime_YDoySod> : fmt::formatter<std::string> | ||
1228 | { | ||
1229 | /// @brief Defines how to format this structs | ||
1230 | /// @param[in] yDoySod Struct to format | ||
1231 | /// @param[in, out] ctx Format context | ||
1232 | /// @return Output iterator | ||
1233 | template<typename FormatContext> | ||
1234 | ✗ | auto format(const NAV::InsTime_YDoySod& yDoySod, FormatContext& ctx) const | |
1235 | { | ||
1236 | ✗ | return fmt::format_to(ctx.out(), "year={}, doy={}, sod={:.6g}", | |
1237 | ✗ | yDoySod.year, yDoySod.doy, static_cast<double>(yDoySod.sod)); | |
1238 | } | ||
1239 | }; | ||
1240 | /// @brief Formatter | ||
1241 | template<> | ||
1242 | struct fmt::formatter<NAV::InsTime> : fmt::formatter<std::string> | ||
1243 | { | ||
1244 | /// @brief Defines how to format this structs | ||
1245 | /// @param[in] insTime Struct to format | ||
1246 | /// @param[in, out] ctx Format context | ||
1247 | /// @return Output iterator | ||
1248 | template<typename FormatContext> | ||
1249 | 12902 | auto format(const NAV::InsTime& insTime, FormatContext& ctx) const | |
1250 | { | ||
1251 |
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()); |
1252 | } | ||
1253 | }; | ||
1254 | |||
1255 | #endif | ||
1256 |