Apollo  6.0
Open source self driving car software
time_conversion.h
Go to the documentation of this file.
1 /******************************************************************************
2  * Copyright 2017 The Apollo Authors. All Rights Reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *****************************************************************************/
16 
17 // Converts GPS timestamp from/to UNIX system timestamp.
18 // This helper is considering leap second.
19 
20 #pragma once
21 
22 #include <stdint.h>
23 
25 
26 namespace apollo {
27 namespace drivers {
28 namespace util {
29 
30 // File expires on: December 2017
31 
32 // There's two concept about 'time'.
33 // 1. Unix time : It counts seconds since Jan 1,1970.
34 // Unix time doesn't include the leap seconds.
35 //
36 // 2. GPS time : It counts seconds since Jan 6,1980.
37 // GPS time does include the leap seconds.
38 //
39 // Leap seconds was added in every a few years, See details:
40 // http://tycho.usno.navy.mil/leapsec.html
41 // https://en.wikipedia.org/wiki/Leap_second
42 //
43 
44 /* leap_seconds table since 1980.
45  +======+========+========+======+========+========+
46  | Year | Jun 30 | Dec 31 | Year | Jun 30 | Dec 31 |
47  +======+========+========+======+========+========+
48  | 1980 | (already +19) | 1994 | +1 | 0 |
49  +------+--------+--------+------+--------+--------+
50  | 1981 | +1 | 0 | 1995 | 0 | +1 |
51  +------+--------+--------+------+--------+--------+
52  | 1982 | +1 | 0 | 1997 | +1 | 0 |
53  +------+--------+--------+------+--------+--------+
54  | 1983 | +1 | 0 | 1998 | 0 | +1 |
55  +------+--------+--------+------+--------+--------+
56  | 1985 | +1 | 0 | 2005 | 0 | +1 |
57  +------+--------+--------+------+--------+--------+
58  | 1987 | 0 | +1 | 2008 | 0 | +1 |
59  +------+--------+--------+------+--------+--------+
60  | 1989 | 0 | +1 | 2012 | +1 | 0 |
61  +------+--------+--------+------+--------+--------+
62  | 1990 | 0 | +1 | 2015 | +1 | 0 |
63  +------+--------+--------+------+--------+--------+
64  | 1992 | +1 | 0 | 2016 | 0 | +1 |
65  +------+--------+--------+------+--------+--------+
66  | 1993 | +1 | 0 | 2017 | 0 | 0 |
67  +------+--------+--------+------+--------+--------+
68 
69  Current TAI - UTC = 37. (mean that: 2017 - 1970/01/01 = 37 seconds)
70 */
71 
72 // We build a lookup table to describe relationship that between UTC and
73 // Leap_seconds.
74 //
75 // Column1: UTC time diff (second).
76 // Shell Example:
77 // date +%s -d"Jan 1, 2017 00:00:00"
78 // return 1483257600.
79 //
80 // date +%s -d"Jan 1, 1970 00:00:00"
81 // return 28800.
82 //
83 // The diff between 1970/01/01 and 2017/01/01 is 1483228800.
84 // (1483257600-28800)
85 //
86 // Column2: Leap seconds diff with GPS basetime(Jan 6,1980).
87 // We Know that The leap_seconds have been already added 37 seconds
88 // util now(2017).
89 // So we can calculate leap_seconds diff between GPS (from Jan 6,1980)
90 // and UTC time.
91 
92 // calc with the formula.
93 static const int32_t LEAP_SECONDS[][2] = {
94  {1483228800, 18}, // 2017/01/01
95  {1435708800, 17}, // 2015/07/01
96  {1341100800, 16}, // 2012/07/01
97  {1230768000, 15}, // 2009/01/01
98  {1136073600, 14}, // 2006/01/01
99  {915148800, 13}, // 1999/01/01
100  {867711600, 12}, // 1997/07/01
101  {820480320, 11}, // 1996/01/01 ;)
102  //....
103  //..
104  // etc.
105 };
106 
107 // seconds that UNIX time afront of GPS, without leap seconds.
108 
109 // Shell:
110 // time1 = date +%s -d"Jan 6, 1980 00:00:00"
111 // time2 = date +%s -d"Jan 1, 1970 00:00:00"
112 // dif_tick = time1-time2
113 // 315964800 = 315993600 - 28800
114 
115 const int32_t GPS_AND_SYSTEM_DIFF_SECONDS = 315964800;
116 
117 template <typename T>
118 T unix2gps(const T unix_seconds) {
119  for (size_t i = 0; i < array_size(LEAP_SECONDS); ++i) {
120  if (unix_seconds >= LEAP_SECONDS[i][0]) {
121  return unix_seconds - (GPS_AND_SYSTEM_DIFF_SECONDS - LEAP_SECONDS[i][1]);
122  }
123  }
124  return static_cast<T>(0);
125 }
126 
127 template <typename T>
128 T gps2unix(const T gps_seconds) {
129  for (size_t i = 0; i < array_size(LEAP_SECONDS); ++i) {
130  T result = gps_seconds + (GPS_AND_SYSTEM_DIFF_SECONDS - LEAP_SECONDS[i][1]);
131  if (result >= LEAP_SECONDS[i][0]) {
132  return result;
133  }
134  }
135  return static_cast<T>(0);
136 }
137 
138 } // namespace util
139 } // namespace drivers
140 } // namespace apollo
T unix2gps(const T unix_seconds)
Definition: time_conversion.h:118
PlanningContext is the runtime context in planning. It is persistent across multiple frames...
Definition: atomic_hash_map.h:25
const int32_t GPS_AND_SYSTEM_DIFF_SECONDS
Definition: time_conversion.h:115
constexpr size_t array_size(T(&)[N])
Definition: macros.h:61
T gps2unix(const T gps_seconds)
Definition: time_conversion.h:128