/src/gpsd/gpsd-3.26.2~dev/gpsd/timebase.c
Line | Count | Source |
1 | | /***************************************************************************** |
2 | | |
3 | | All of gpsd's assumptions about time and GPS time reporting live in this file. |
4 | | |
5 | | This is a work in progress. Currently (3.11) GPSD requires that the host |
6 | | system clock be accurate to within one second. It would be nice to relax |
7 | | this to "accurate within one GPS rollover period" for receivers reporting |
8 | | GPS week+TOW, but this isn't possible in general. |
9 | | |
10 | | = Begin Sidebar: Why Leap Seconds = |
11 | | |
12 | | Read this carefully, and if there are errors, please correct. An |
13 | | understanding of the following terms is critical to make sense of the |
14 | | situation, which would be farcical if it were not serious. |
15 | | |
16 | | We discuss four timescales: |
17 | | |
18 | | 1. TAI, International Atomic Time, which ticks smoothly |
19 | | at the rate of the SI second. TAI has no concept of a day, year, etc. |
20 | | TAI does not define "days" or large units, and is hence difficult |
21 | | for humans to parse. Also, TAI is not broadcast or generally available. |
22 | | 2. GPS Time, which ticks at at the rate of TAI, but has a constant offset |
23 | | from it. For other GNSS systems, the offset is different. The |
24 | | offset is of purely historical interest, being chosen by each |
25 | | GNSS operator for convenience when the systems were inaugurated. |
26 | | In other words, only the "epoch" differs between GPS Time and TAI. |
27 | | 3. UT1, a smoothed earth rotation angle, which MUST return to zero |
28 | | once a day, (why? Because you want the sun to be overhead *each* |
29 | | day at the same time on your watch, no?), and ticks SI seconds |
30 | | (a non-integeral number of seconds will occur in a UT1 day, |
31 | | obviously). For those of you who still say "GMT", UT1 is the |
32 | | closest modern timescale. |
33 | | 4. UTC, Coordinated Universal Time, which ticks SI seconds. An attempt is |
34 | | made to keep UTC aligned with the rate of flow of seconds (TAI), and |
35 | | the rate of flow of days (UT1). |
36 | | |
37 | | The reason UTC has to struggle has little to do with the fact that the earth's |
38 | | rotation is slowing down. Although the length of the day, as measured by UT1, |
39 | | is lengthening in terms of the SI second, this is a very long term slowdown, |
40 | | and since 1980, the earth has actually speeded up. |
41 | | |
42 | | The issue simply is that the term "second" is defined in two incompatible ways: |
43 | | |
44 | | Def 1. As a fixed number (9,192,631,770) of cycles of an atomic standard. |
45 | | We believe this is a constant, and evidence to the contrary may |
46 | | involve GPSD code review, and Nobel Prizes. This is the SI second. |
47 | | Def 2. As 1/86400 of a "day". The number 86400 arises from |
48 | | 1 day == 24 * 60 * 60 secs. This is what we learn in school. |
49 | | |
50 | | Both of these have been defined separately, and the issue of leap seconds, |
51 | | rubber seconds, Smoothed Leap Seconds, etc, arises because we are |
52 | | unwilling to change the definition of either to be a derived unit of the |
53 | | other. |
54 | | |
55 | | At the time the SI second was defined, it was believed that Def 2 was correct, |
56 | | and the number in Def 1 was derived. Because of ease of measurement, Def 1 was |
57 | | codified, and the problem was ignored for some time. Prior to 1972, |
58 | | complicated formulae were used to scale the SI second, with the attendant |
59 | | confusion and fear when the formula would be revised. |
60 | | |
61 | | Since 1972, the start of UTC, the decision to have leap seconds means that UTC |
62 | | ticks SI seconds. Every 86400 SI seconds, we declare a new day, and we let the |
63 | | error (UT1 - UTC) build up. This is of the order of a few ms each midnight, not |
64 | | always the same way (think earthquakes that move the earth's crust). |
65 | | |
66 | | Once the error has built up substantially, every few years, we (and by |
67 | | "we", I mean M. Daniel Gambis at the IERS) declare that a future |
68 | | day will have 86401 secs. This is the Leap Second. Note that this |
69 | | often overcorrects, but if we wait a few months, the error will disappear. |
70 | | |
71 | | An animation of this process is available at: |
72 | | https://space-geodesy.nasa.gov/multimedia/videos/EarthOrientationAnimations/UT1/UT1.html |
73 | | |
74 | | Clear? |
75 | | |
76 | | Two last things: |
77 | | 1. Again, the earth slowing down is NOT the cause of leap seconds, |
78 | | except very indirectly. It is the conflict between the two |
79 | | definitions above that causes leap seconds |
80 | | 2. POSIX declares that there is no conflict, there are always 86400 SI |
81 | | secs in a day, and hence no leap seconds. The fact that ostriches |
82 | | survive in the wild indicates that this is not as mind-crushingly |
83 | | wrong as it may seem. |
84 | | |
85 | | = End Sidebar = |
86 | | |
87 | | Date and time in GPS is represented as number of weeks mod 1024 from |
88 | | 1980-01-06T00:00.00Z, and number of SI seconds into the week. GPS |
89 | | time is not leap-second corrected, and has a constant offset from TAI, |
90 | | but not from UTC. |
91 | | |
92 | | There are hence two issues with converting GPS Time to UTC: |
93 | | |
94 | | 1. We need to recover the epoch difference between TAI and GPS Time, |
95 | | which rolls over to 0 every 1024 weeks (approx 20 years). Think |
96 | | of this as analogous to the Y2K problem; we do not know if we are |
97 | | off by 1024 weeks. This is the "rollover" issue below. |
98 | | 2. Once we have the epoch right, we need to adjust for Leap Seconds |
99 | | that have been issued. |
100 | | |
101 | | (Complicating the issue is that most consumer devices may not apply |
102 | | the corrections when rollover occurs, as this may not be adequately |
103 | | tested. We hence have to accept the UTC time reported by the device, |
104 | | while checking it on the sly). |
105 | | |
106 | | Satellites also broadcast a current leap-second correction which is |
107 | | updated on (theoretically) three-month boundaries according to |
108 | | rotational bulletins issued by the International Earth Rotation and |
109 | | Reference Systems Service (IERS). Historically all corrections have |
110 | | been made on six-month boundaries. |
111 | | |
112 | | The leap-second correction is only included in the satellite subframe |
113 | | broadcast, roughly once ever 20 minutes. While the satellites do |
114 | | notify GPSes of upcoming leap-seconds, this notification is not |
115 | | necessarily processed correctly on consumer-grade devices, and will |
116 | | not be available at all when a GPS receiver has just |
117 | | cold-booted. Thus, the time reported from GPS devices, although |
118 | | supposed to be UTC, may be offset by an integer number of seconds |
119 | | between a cold boot or leap second and the following |
120 | | subframe broadcast. |
121 | | |
122 | | It might be best not to trust time for 20 minutes after GPSD startup |
123 | | if it is more than 500ms from current system time (that is long enough |
124 | | for an ephemeris to load) but this isn't actually implemented as the |
125 | | divergence will normally be only one second or less. |
126 | | |
127 | | GPS date and time are subject to a rollover problem in the 10-bit week |
128 | | number counter, which will re-zero every 1024 weeks (roughly every 20 |
129 | | years). The first rollover was 1999-08-22T00:00:00; the most recent |
130 | | was 2019-04-07T00:00:00. Note that both these time stamps are in GPS |
131 | | Time, not UTC (the recent rollover occurred at 2019-04-06T23:59:42Z). |
132 | | Plans are afoot to upgrade the message format to 13 bits; this |
133 | | will delay the next rollover until 2173. |
134 | | |
135 | | For accurate time reporting, therefore, a GPS requires a supplemental |
136 | | time reference sufficient to identify the current rollover period, |
137 | | e.g. accurate to within 512 weeks. Many GPSes have a wired-in |
138 | | assumption about the UTC time of the last rollover and will thus report |
139 | | incorrect times outside the rollover period they were designed in. |
140 | | |
141 | | These conditions leave gpsd in a serious hole. Actually there are several |
142 | | interrelated problems: |
143 | | |
144 | | 1) Every device has some assumption about base epoch (date of |
145 | | last rollover) that we don't have access to. Thus, there's no way to |
146 | | check whether a rollover the device wasn't prepared for has occurred |
147 | | before gpsd startup time (making the reported UTC date invalid) |
148 | | without some other time source. (Some devices may keep a |
149 | | rollover count in NVRAM and avoid the problem; we can't tell when that's |
150 | | happening, either.) |
151 | | |
152 | | 2) Many NMEA devices - in fact, all that don't report ZDA - never tell |
153 | | us what century they think it is. Those that do report century are |
154 | | still subject to rollover problems. We need an external time reference |
155 | | for this, too. |
156 | | |
157 | | 3) Supposing we're looking at a binary protocol that returns week/tow, |
158 | | we can't know which rollover period we're in without an external time |
159 | | source. |
160 | | |
161 | | 4) Only one external time source, the host system clock, is reliably |
162 | | available, although it may not be accurate. |
163 | | |
164 | | 5) Another source *may* be available - the GPS leap second count, if we can |
165 | | get the device to report it. The latter is not a given; SiRFs before |
166 | | firmware rev 2.3.2 don't report it unless special subframe data reporting |
167 | | is enabled, which requires 38400bps. Evermore GPSes can't be made to |
168 | | report it at all. Furthermore, before the almanac load the GPS may report |
169 | | a fixed (and possibly out of date) offset. |
170 | | |
171 | | Conclusion: if the system clock isn't accurate enough that we can |
172 | | deduce what rollover period we're in, we're utterly |
173 | | hosed. Furthermore, if it's not accurate to within a second and only |
174 | | NMEA devices that don't emit ZDA are reporting, we don't even know |
175 | | what century it is! |
176 | | |
177 | | Therefore, we must assume the system clock is reliable to within a second. |
178 | | |
179 | | However, none of these caveats affect the usefulness of PPS, which |
180 | | tells us top of second to theoretical 50ns accuracy (actually about 1 |
181 | | microsecond over RS232 and roughly one poll interval over USB) and can |
182 | | be made to condition a local NTP instance that does *not* rely on the |
183 | | system clock. The combination of PPS with NTP time should be reliable |
184 | | regardless of what the local system clock gets up to. That is, unless |
185 | | NTP clock skew goes over 1 second, but this is unlikely to ever happen |
186 | | - and if it does the reasons will have nothing to do with GPS |
187 | | idiosyncrasies. |
188 | | |
189 | | This file is Copyright 2010 by the GPSD project |
190 | | SPDX-License-Identifier: BSD-2-clause |
191 | | |
192 | | *****************************************************************************/ |
193 | | |
194 | | #include "../include/gpsd_config.h" // must be before all includes |
195 | | |
196 | | #include <ctype.h> |
197 | | #include <stdlib.h> |
198 | | #include <string.h> |
199 | | |
200 | | #include "../include/gpsd.h" |
201 | | |
202 | | // initialize the GPS context's time fields |
203 | | void gpsd_time_init(struct gps_context_t *context, time_t starttime) |
204 | 0 | { |
205 | | /* |
206 | | * gpsd can't work with 'right' timezones (leapseconds inserted in |
207 | | * the timezone offset). Avoid this and all manner of other local |
208 | | * time issues by telling the system we want times returned in UTC. |
209 | | */ |
210 | 0 | (void)putenv("TZ=UTC"); |
211 | | |
212 | | /* |
213 | | * Provides a start time for getting the century. Do this, just |
214 | | * in case one of our embedded deployments is still in place in |
215 | | * the year 2.1K. Still likely to fail if we bring up the daemon |
216 | | * just before a century mark, but that case is probably doomed |
217 | | * anyhow because of 2-digit years. |
218 | | */ |
219 | 0 | context->leap_seconds = BUILD_LEAPSECONDS; |
220 | 0 | context->century = BUILD_CENTURY; |
221 | 0 | context->start_time = starttime; |
222 | |
|
223 | 0 | context->rollovers = (int)((context->start_time - GPS_EPOCH) / |
224 | 0 | GPS_ROLLOVER); |
225 | |
|
226 | 0 | if (GPS_EPOCH > context->start_time) { |
227 | 0 | GPSD_LOG(LOG_ERROR, &context->errout, |
228 | 0 | "system time looks bogus, dates may not be reliable.\n"); |
229 | 0 | } else { |
230 | | // we've forced the UTC timezone, so this is actually UTC |
231 | 0 | struct tm *now = localtime(&context->start_time); |
232 | 0 | char scr[128]; |
233 | 0 | timespec_t ts_start_time; |
234 | |
|
235 | 0 | ts_start_time.tv_sec = context->start_time; |
236 | 0 | ts_start_time.tv_nsec = 0; |
237 | | |
238 | | /* |
239 | | * This is going to break our regression-test suite once a century. |
240 | | * I think we can live with that consequence. |
241 | | */ |
242 | 0 | now->tm_year += 1900; |
243 | 0 | context->century = now->tm_year - (now->tm_year % 100); |
244 | 0 | GPSD_LOG(LOG_INF, &context->errout, "startup at %s (%ld)\n", |
245 | 0 | timespec_to_iso8601(ts_start_time, scr, sizeof(scr)), |
246 | 0 | (long)context->start_time); |
247 | 0 | } |
248 | 0 | } |
249 | | |
250 | | /* |
251 | | * Interpret "#Date: yyyy-mm-dd", setting the session context |
252 | | * start time. We do this so the behavior of the |
253 | | * regression tests won't depend on current system time. |
254 | | */ |
255 | | void gpsd_set_century(struct gps_device_t *session) |
256 | 0 | { |
257 | 0 | int ret; |
258 | 0 | unsigned year = 0; |
259 | 0 | unsigned month = 0; |
260 | 0 | unsigned day = 0; |
261 | 0 | struct gps_context_t *context = session->context; |
262 | 0 | struct tm date = {0}; |
263 | |
|
264 | 0 | ret = sscanf((const char *)session->lexer.outbuffer, "# Date: %u-%u-%u", |
265 | 0 | &year, &month, &day); |
266 | 0 | if (1 > ret) { |
267 | | // give up unless we at least got a year |
268 | 0 | return; |
269 | 0 | } |
270 | | |
271 | 0 | if (!IN(1968, year, 2200)) { |
272 | | // bad year |
273 | 0 | return; |
274 | 0 | } |
275 | | |
276 | 0 | context->century = year - (year % 100); |
277 | |
|
278 | 0 | date.tm_year = year - 1900; // year, 1999..2099 |
279 | 0 | if (!IN(1, month, 12)) { |
280 | 0 | month = 1; |
281 | 0 | } |
282 | 0 | date.tm_mon = month - 1; // month 0..11 |
283 | 0 | if (!IN(1, day, 31)) { |
284 | 0 | day = 1; |
285 | 0 | } |
286 | 0 | date.tm_mday = day; // day 1..31 |
287 | 0 | context->start_time = mkgmtime(&date); |
288 | 0 | context->rollovers = (int)((context->start_time - GPS_EPOCH) / |
289 | 0 | GPS_ROLLOVER); |
290 | |
|
291 | 0 | GPSD_LOG(LOG_PROG, &context->errout, |
292 | 0 | "Setting century: %d rollovers %d %d-%d-%d\n", |
293 | 0 | context->century, context->rollovers, year, month, day); |
294 | |
|
295 | 0 | gpsd_time_init(context, context->start_time); |
296 | 0 | } |
297 | | |
298 | | // resolve a UTC date, checking for rollovers |
299 | | timespec_t gpsd_utc_resolve(struct gps_device_t *session) |
300 | 0 | { |
301 | | /* |
302 | | * We'd like to *correct* for rollover the way we do for GPS week. |
303 | | * In theory, comparing extracted UTC against present time should |
304 | | * allow us to compute the device's epoch assumption. In practice, |
305 | | * this will be hairy and risky. |
306 | | */ |
307 | 0 | timespec_t t; |
308 | |
|
309 | 0 | t.tv_sec = (time_t)mkgmtime(&session->nmea.date); |
310 | 0 | t.tv_nsec = session->nmea.subseconds.tv_nsec; |
311 | 0 | session->context->valid &=~ GPS_TIME_VALID; |
312 | | |
313 | | /* |
314 | | * If the system clock is zero or has a small-integer value, |
315 | | * Time is from before GPS satellites werelaunched! |
316 | | * |
317 | | * Or, start time from regression log. |
318 | | * |
319 | | * No further sanity-checking is possible. |
320 | | */ |
321 | 0 | if (GPS_EPOCH > session->context->start_time || |
322 | 0 | 1 == session->regression) { |
323 | 0 | return t; |
324 | 0 | } |
325 | | |
326 | | #if 0 // Debug |
327 | | GPSD_LOG(LOG_IO, &session->context->errout, |
328 | | "leaps %d GPS_EPOCH %lld > start_time %lld\n", |
329 | | session->context->leap_seconds, |
330 | | (long long)GPS_EPOCH, |
331 | | (long long)session->context->start_time); |
332 | | #endif |
333 | | |
334 | | /* sanity check unix time against leap second. |
335 | | * Does not work well with regressions because the leap_sconds |
336 | | * could be from the receiver, or from BUILD_LEAPSECONDS. |
337 | | * Leap second 18 at 1 Jan 2017: 1483228800 |
338 | | * (long long) for 32-bit systems */ |
339 | 0 | if (17 < session->context->leap_seconds && |
340 | 0 | 1483228800LL > t.tv_sec) { |
341 | 0 | long long old_tv_sec = t.tv_sec; |
342 | 0 | char scr[128]; |
343 | |
|
344 | 0 | t.tv_sec += 619315200LL; // fast forward 1024 weeks |
345 | 0 | (void)gmtime_r(&t.tv_sec, &session->nmea.date); // fix NMEA date |
346 | 0 | (void)timespec_to_iso8601(t, scr, sizeof(scr)); |
347 | 0 | GPSD_LOG(LOG_WARN, &session->context->errout, |
348 | 0 | "WKRO bug: leap second %d inconsistent " |
349 | 0 | "with %lld, corrected to %lld (%s)\n", |
350 | 0 | session->context->leap_seconds, |
351 | 0 | old_tv_sec, (long long)t.tv_sec, scr); |
352 | 0 | } |
353 | | |
354 | | /* |
355 | | * If the GPS is reporting a time from before the daemon started, |
356 | | * maybe we've had a rollover event while the daemon was running. |
357 | | */ |
358 | |
|
359 | 0 | return t; |
360 | 0 | } |
361 | | |
362 | | void gpsd_century_update(struct gps_device_t *session, int century) |
363 | 0 | { |
364 | 0 | session->context->valid |= CENTURY_VALID; |
365 | 0 | if (century > session->context->century) { |
366 | | /* |
367 | | * This mismatch is almost certainly not due to a GPS week |
368 | | * rollover, because that would throw the ZDA report backward |
369 | | * into the last rollover period instead of forward. Almost |
370 | | * certainly it means that a century mark has passed while |
371 | | * gpsd was running, and we should trust the new ZDA year. |
372 | | */ |
373 | 0 | GPSD_LOG(LOG_WARN, &session->context->errout, |
374 | 0 | "century rollover detected.\n"); |
375 | 0 | session->context->century = century; |
376 | 0 | } else if (GPS_EPOCH <= session->context->start_time && |
377 | 0 | century < session->context->century) { |
378 | | /* |
379 | | * This looks like a GPS week-counter rollover. |
380 | | */ |
381 | 0 | GPSD_LOG(LOG_WARN, &session->context->errout, |
382 | 0 | "ZDA year less than clock year, " |
383 | 0 | "probable GPS week rollover lossage\n"); |
384 | 0 | session->context->valid &=~ CENTURY_VALID; |
385 | 0 | } |
386 | 0 | } |
387 | | |
388 | | /* gpsd_gpstime() convert GPS week/tow to "GPS time" |
389 | | * "GPS time" as defined by RINEX: GPS time + leap seconds == UTC |
390 | | * |
391 | | * Use for time that is not "time now in UTC". |
392 | | * Do not touch: gps_week, gps_tow, GPS_VALID, rollovers in context. |
393 | | */ |
394 | | timespec_t gpsd_gpstime(struct gps_device_t *session, |
395 | | unsigned week, timespec_t tow) |
396 | 0 | { |
397 | 0 | timespec_t t; |
398 | |
|
399 | 0 | if (1024 <= week) { |
400 | | // we have a full, not truncated, week |
401 | 0 | } else { |
402 | | // truncated week, add in the roll overs |
403 | 0 | week += session->context->rollovers * 1024; |
404 | 0 | } |
405 | | |
406 | | // gcc needs the (time_t)week to not overflow. clang got it right. |
407 | | // if time_t is 32-bits, then still 2038 issues |
408 | | // no leap seconds |
409 | 0 | t.tv_sec = GPS_EPOCH + ((time_t)week * SECS_PER_WEEK) + tow.tv_sec; |
410 | 0 | t.tv_nsec = tow.tv_nsec; |
411 | |
|
412 | 0 | #if 4 < SIZEOF_TIME_T |
413 | | // 2038 rollover hack for unsigned 32-bit time, assuming today is < 2038 |
414 | 0 | if (0 > t.tv_sec) { |
415 | | // recompute for previous EPOCH |
416 | 0 | week -= 1024; |
417 | 0 | t.tv_sec = GPS_EPOCH + ((time_t)week * SECS_PER_WEEK) + tow.tv_sec; |
418 | 0 | GPSD_LOG(LOG_WARN, &session->context->errout, |
419 | 0 | "gpsd_gpstime(): 2038 rollover. Adjusting to %lld week %u\n", |
420 | 0 | (long long)t.tv_sec, week); |
421 | 0 | } |
422 | 0 | #endif // SIZEOF_TIME_T |
423 | |
|
424 | 0 | return t; |
425 | 0 | } |
426 | | |
427 | | /* gpsd_gpstime_resolv() convert GPS week/tow to UTC as a timespec |
428 | | * using current leap second. |
429 | | * |
430 | | * Sets gps_week, gps_tow, GPS_VALID, rollovers, in context. |
431 | | * FIXME: this prolly should call gpsd_resolv() instead of duplicating it. |
432 | | */ |
433 | | timespec_t gpsd_gpstime_resolv(struct gps_device_t *session, |
434 | | unsigned week, timespec_t tow) |
435 | 0 | { |
436 | 0 | timespec_t t; |
437 | | |
438 | | /* |
439 | | * This code detects and compensates for week counter rollovers that |
440 | | * happen while gpsd is running. It will not save you if there was a |
441 | | * rollover that confused the receiver before gpsd booted up. It *will* |
442 | | * work even when Block IIF satellites increase the week counter width |
443 | | * to 13 bits. |
444 | | */ |
445 | 0 | if ((int)week < (session->context->gps_week & 0x3ff)) { |
446 | 0 | ++session->context->rollovers; |
447 | 0 | GPSD_LOG(LOG_INF, &session->context->errout, |
448 | 0 | "GPS week %u 10-bit rollover detected. rollovers %d\n", |
449 | 0 | week, session->context->rollovers); |
450 | 0 | } |
451 | | |
452 | | /* |
453 | | * This guard copes with both conventional GPS weeks and the "extended" |
454 | | * 15-or-16-bit version with no wraparound that appears in Zodiac |
455 | | * chips and is supposed to appear in the Geodetic Navigation |
456 | | * Information (0x29) packet of SiRF chips. Some SiRF firmware versions |
457 | | * (notably 231) actually ship the wrapped 10-bit week, despite what |
458 | | * the protocol reference claims. |
459 | | */ |
460 | 0 | if (1024 > week) { |
461 | 0 | week += session->context->rollovers * 1024; |
462 | 0 | } |
463 | | |
464 | | /* This used to sanity check week number, GPS epoch, against leap |
465 | | * seconds. Did not work well with regressions because the leap_sconds |
466 | | * could be from the receiver, or from BUILD_LEAPSECONDS. |
467 | | * Maybe if the regressions files provided BUILD_LEAPSECONDS this |
468 | | * could be tried again. |
469 | | */ |
470 | | |
471 | | // gcc needs the (time_t)week to not overflow. clang got it right. |
472 | | // if time_t is 32-bits, then still 2038 issues |
473 | 0 | t.tv_sec = GPS_EPOCH + ((time_t)week * SECS_PER_WEEK) + tow.tv_sec; |
474 | 0 | t.tv_sec -= session->context->leap_seconds; |
475 | 0 | t.tv_nsec = tow.tv_nsec; |
476 | |
|
477 | 0 | #if 4 < SIZEOF_TIME_T |
478 | | // 2038 rollover hack for unsigned 32-bit time, assuming today is < 2038 |
479 | 0 | if (0 > t.tv_sec) { |
480 | | // recompute for previous EPOCH |
481 | 0 | week -= 1024; |
482 | 0 | t.tv_sec = GPS_EPOCH + ((time_t)week * SECS_PER_WEEK) + tow.tv_sec; |
483 | 0 | t.tv_sec -= session->context->leap_seconds; |
484 | 0 | GPSD_LOG(LOG_WARN, &session->context->errout, |
485 | 0 | "2038 rollover. Adjusting to %lld. week %u leap %d\n", |
486 | 0 | (long long)t.tv_sec, week, |
487 | 0 | session->context->leap_seconds); |
488 | 0 | } |
489 | 0 | #endif // SIZEOF_TIME_T |
490 | |
|
491 | 0 | session->context->gps_week = week; |
492 | 0 | session->context->gps_tow = tow; |
493 | 0 | session->context->valid |= GPS_TIME_VALID; |
494 | |
|
495 | 0 | return t; |
496 | 0 | } |
497 | | |
498 | | // vim: set expandtab shiftwidth=4 |