TimeSystem.cpp
Go to the documentation of this file.
1 //==============================================================================
2 //
3 // This file is part of GNSSTk, the ARL:UT GNSS Toolkit.
4 //
5 // The GNSSTk is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU Lesser General Public License as published
7 // by the Free Software Foundation; either version 3.0 of the License, or
8 // any later version.
9 //
10 // The GNSSTk is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU Lesser General Public License for more details.
14 //
15 // You should have received a copy of the GNU Lesser General Public
16 // License along with GNSSTk; if not, write to the Free Software Foundation,
17 // Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
18 //
19 // This software was developed by Applied Research Laboratories at the
20 // University of Texas at Austin.
21 // Copyright 2004-2022, The Board of Regents of The University of Texas System
22 //
23 //==============================================================================
24 
25 //==============================================================================
26 //
27 // This software was developed by Applied Research Laboratories at the
28 // University of Texas at Austin, under contract to an agency or agencies
29 // within the U.S. Department of Defense. The U.S. Government retains all
30 // rights to use, duplicate, distribute, disclose, or release this software.
31 //
32 // Pursuant to DoD Directive 523024
33 //
34 // DISTRIBUTION STATEMENT A: This software has been approved for public
35 // release, distribution is unlimited.
36 //
37 //==============================================================================
38 
39 #include <cmath>
40 #include "TimeSystem.hpp"
41 #include "TimeConverters.hpp"
42 #include "Exception.hpp"
43 
44 using namespace std;
45 
46 namespace gnsstk
47 {
48  ostream& operator<<(ostream& os, const TimeSystem ts)
49  {
50  return os << StringUtils::asString(ts);
51  }
52 
53  double getLeapSeconds(const int year,
54  const int month,
55  const double day)
56  {
57  // Leap second data
58  // number of changes before leap seconds (1960-1971) - this
59  // should never change.
60  static const int NPRE=14;
61 
62  // epoch year, epoch month(1-12), delta t(sec), rate
63  // (sec/day) for [1960,1972).
64  static const struct {
65  int year, month;
66  double delt, rate;
67  } preleap[NPRE] = {
68  { 1960, 1, 1.4178180, 0.0012960 },
69  { 1961, 1, 1.4228180, 0.0012960 },
70  { 1961, 8, 1.3728180, 0.0012960 },
71  { 1962, 1, 1.8458580, 0.0011232 },
72  { 1963, 11, 1.9458580, 0.0011232 },
73  { 1964, 1, 3.2401300, 0.0012960 },
74  { 1964, 4, 3.3401300, 0.0012960 },
75  { 1964, 9, 3.4401300, 0.0012960 },
76  { 1965, 1, 3.5401300, 0.0012960 },
77  { 1965, 3, 3.6401300, 0.0012960 },
78  { 1965, 7, 3.7401300, 0.0012960 },
79  { 1965, 9, 3.8401300, 0.0012960 },
80  { 1966, 1, 4.3131700, 0.0025920 },
81  { 1968, 2, 4.2131700, 0.0025920 }
82  };
83 
84  // Leap seconds history
85  // ***** This table must be updated for new leap seconds **************
86  static const struct {
87  int year, month, nleap;
88  } leaps[] = {
89  { 1972, 1, 10 },
90  { 1972, 7, 11 },
91  { 1973, 1, 12 },
92  { 1974, 1, 13 },
93  { 1975, 1, 14 },
94  { 1976, 1, 15 },
95  { 1977, 1, 16 },
96  { 1978, 1, 17 },
97  { 1979, 1, 18 },
98  { 1980, 1, 19 },
99  { 1981, 7, 20 },
100  { 1982, 7, 21 },
101  { 1983, 7, 22 },
102  { 1985, 7, 23 },
103  { 1988, 1, 24 },
104  { 1990, 1, 25 },
105  { 1991, 1, 26 },
106  { 1992, 7, 27 },
107  { 1993, 7, 28 },
108  { 1994, 7, 29 },
109  { 1996, 1, 30 },
110  { 1997, 7, 31 },
111  { 1999, 1, 32 },
112  { 2006, 1, 33 },
113  { 2009, 1, 34 },
114  { 2012, 7, 35 },
115  { 2015, 7, 36 },
116  { 2017, 1, 37 }, // leave the last comma!
117  // add new entry here, of the form:
118  // { year, month(1-12), leap_sec }, // leave the last comma!
119  };
120 
121  // the number of leaps (do not change this)
122  static const int NLEAPS = sizeof(leaps)/sizeof(leaps[0]);
123 
124  // last year in leaps
125  //static const int MAXYEAR = leaps[NLEAPS-1].year;
126 
127  // END static data
128 
129  // search for the input year, month
130  if (year < 1960)
131  {
132  // pre-1960 no deltas
133  }
134  else if (month < 1 || month > 12)
135  {
136  // blunder, should never happen - throw?
137  }
138  else if (year < 1972)
139  {
140  // [1960-1972) pre-leap
141  for (int i=NPRE-1; i>=0; i--)
142  {
143  if (preleap[i].year > year ||
144  (preleap[i].year == year && preleap[i].month > month))
145  {
146  continue;
147  }
148 
149  // found last record with < rec.year >= year and
150  // rec.month >= month
151  // watch out - cannot use CommonTime here
152  int iday(static_cast<int>(day));
153  double dday(static_cast<double>(iday-int(day)));
154  if (iday == 0)
155  {
156  iday = 1;
157  dday = 1.0-dday;
158  }
159  long JD0 = convertCalendarToJD(year,month,iday);
160  long JD = convertCalendarToJD(preleap[i].year,preleap[i].month,1);
161  return (preleap[i].delt + (double(JD0-JD)+dday)*preleap[i].rate);
162  }
163  }
164  else
165  { // [1972- leap seconds
166  for (int i=NLEAPS-1; i>=0; i--)
167  {
168  if (leaps[i].year > year ||
169  (leaps[i].year == year && leaps[i].month > month))
170  {
171  continue;
172  }
173  return double(leaps[i].nleap);
174  }
175  }
176 
177  return 0.0;
178  }
179 
180 
182  const TimeSystem outTS,
183  const int year,
184  const int month,
185  const double day)
186  {
187  double dt(0.0);
188 
189  // identity
190  if (inTS == outTS)
191  return dt;
192 
193  // cannot convert unknowns
194  if (inTS == TimeSystem::Unknown || outTS == TimeSystem::Unknown)
195  {
196  Exception e("Cannot compute correction for TimeSystem::Unknown");
197  GNSSTK_THROW(e);
198  }
199 
200  // compute TT-TDB here; ref Astronomical Almanac B7
201  double TDBmTT(0.0);
202  if (inTS == TimeSystem::TDB || outTS == TimeSystem::TDB)
203  {
204  int iday = int(day);
205  long jday = convertCalendarToJD(year, month, iday) ;
206  double frac(day-iday);
207  double TJ2000(jday-2451545.5+frac); // t-J2000
208  // 0.0001657 sec * sin(357.53 + 0.98560028 * TJ2000 deg)
209  frac = ::fmod(0.017201969994578 * TJ2000, 6.2831853071796);
210  TDBmTT = 0.0001657 * ::sin(6.240075674 + frac);
211  // 0.000022 sec * sin(246.11 + 0.90251792 * TJ2000 deg)
212  frac = ::fmod(0.015751909262251 * TJ2000, 6.2831853071796);
213  TDBmTT += 0.000022 * ::sin(4.295429822 + frac);
214  }
215 
216  // Time system conversions constants
217  static const double TAI_minus_GPSGAL_EPOCH = 19.;
218  static const double TAI_minus_BDT_EPOCH = 33.;
219  static const double TAI_minus_TT_EPOCH = -32.184;
220 
221  // -----------------------------------------------------------
222  // conversions: first convert inTS->TAI ...
223  // TAI = GPS + 19s
224  // TAI = UTC + getLeapSeconds()
225  // TAI = TT - 32.184s
226  if (inTS == TimeSystem::GPS || // GPS -> TAI
227  inTS == TimeSystem::GAL || // GAL -> TAI
228  inTS == TimeSystem::QZS || // QZS -> TAI
229  inTS == TimeSystem::IRN ) // IRN -> TAI
230  {
231  dt = TAI_minus_GPSGAL_EPOCH;
232  }
233  else if (inTS == TimeSystem::UTC || // UTC -> TAI
234  inTS == TimeSystem::GLO) // GLO -> TAI
235  {
236  dt = getLeapSeconds(year, month, day);
237  }
238  else if (inTS == TimeSystem::BDT) // BDT -> TAI
239  {
240  dt = TAI_minus_BDT_EPOCH;
241  }
242  else if (inTS == TimeSystem::TAI) // TAI
243  {
244  }
245  else if (inTS == TimeSystem::TT) // TT -> TAI
246  {
247  dt = TAI_minus_TT_EPOCH;
248  }
249  else if (inTS == TimeSystem::TDB) // TDB -> TAI
250  {
251  dt = TAI_minus_TT_EPOCH + TDBmTT;
252  }
253  else
254  { // other
255  Exception e("Invalid input TimeSystem " + StringUtils::asString(inTS));
256  GNSSTK_THROW(e);
257  }
258 
259  // -----------------------------------------------------------
260  // ... then convert TAI->outTS
261  // GPS = TAI - 19s
262  // UTC = TAI - getLeapSeconds()
263  // TT = TAI + 32.184s
264  if (outTS == TimeSystem::GPS || // TAI -> GPS
265  outTS == TimeSystem::GAL || // TAI -> GAL
266  outTS == TimeSystem::QZS || // TAI -> QZS
267  outTS == TimeSystem::IRN ) // TAI -> IRN
268  {
269  dt -= TAI_minus_GPSGAL_EPOCH;
270  }
271  else if (outTS == TimeSystem::UTC || // TAI -> UTC
272  outTS == TimeSystem::GLO) // TAI -> GLO
273  {
274  dt -= getLeapSeconds(year, month, day);
275  }
276  else if (outTS == TimeSystem::BDT) // TAI -> BDT
277  {
278  dt -= TAI_minus_BDT_EPOCH;
279  }
280  else if (outTS == TimeSystem::TAI) // TAI
281  {
282  }
283  else if (outTS == TimeSystem::TT) // TAI -> TT
284  {
285  dt -= TAI_minus_TT_EPOCH;
286  }
287  else if (outTS == TimeSystem::TDB) // TAI -> TDB
288  {
289  dt -= TAI_minus_TT_EPOCH + TDBmTT;
290  }
291  else
292  { // other
293  Exception e("Invalid output TimeSystem "+StringUtils::asString(outTS));
294  GNSSTK_THROW(e);
295  }
296 
297  return dt;
298  }
299 
300 
301  namespace StringUtils
302  {
303  std::string asString(TimeSystem ts)
304  {
305  switch (ts)
306  {
307  case TimeSystem::Unknown: return "UNK";
308  case TimeSystem::Any: return "Any";
309  case TimeSystem::GPS: return "GPS";
310  case TimeSystem::GLO: return "GLO";
311  case TimeSystem::GAL: return "GAL";
312  case TimeSystem::QZS: return "QZS";
313  case TimeSystem::BDT: return "BDT";
314  case TimeSystem::IRN: return "IRN";
315  case TimeSystem::UTC: return "UTC";
316  case TimeSystem::TAI: return "TAI";
317  case TimeSystem::TT: return "TT";
318  case TimeSystem::TDB: return "TDB";
319  default: return "???";
320  }
321  }
322 
323 
324  TimeSystem asTimeSystem(const std::string& s)
325  {
326  if (s == "UNK") return TimeSystem::Unknown;
327  if (s == "Any") return TimeSystem::Any;
328  if (s == "GPS") return TimeSystem::GPS;
329  if (s == "GLO") return TimeSystem::GLO;
330  if (s == "GAL") return TimeSystem::GAL;
331  if (s == "QZS") return TimeSystem::QZS;
332  if (s == "BDT") return TimeSystem::BDT;
333  if (s == "IRN") return TimeSystem::IRN;
334  if (s == "UTC") return TimeSystem::UTC;
335  if (s == "TAI") return TimeSystem::TAI;
336  if (s == "TT") return TimeSystem::TT;
337  if (s == "TDB") return TimeSystem::TDB;
338  return TimeSystem::Unknown;
339  }
340  }
341 
342 } // end namespace
TimeSystem.hpp
example6.day
day
Definition: example6.py:66
example6.year
year
Definition: example6.py:64
gnsstk
For Sinex::InputHistory.
Definition: BasicFramework.cpp:50
std::sin
double sin(gnsstk::Angle x)
Definition: Angle.hpp:144
gnsstk::Exception
Definition: Exception.hpp:151
gnsstk::StringUtils::asTimeSystem
TimeSystem asTimeSystem(const std::string &s)
Convert a string representation of TimeSystem to an enum.
Definition: TimeSystem.cpp:324
gnsstk::TimeSystem
TimeSystem
Definition of various time systems.
Definition: TimeSystem.hpp:51
TimeConverters.hpp
gnsstk::StringUtils::asString
std::string asString(TimeSystem ts)
Convert a TimeSystem enum to its string representation.
Definition: TimeSystem.cpp:303
std::operator<<
std::ostream & operator<<(std::ostream &s, gnsstk::StringUtils::FFLead v)
Definition: FormattedDouble_T.cpp:44
Exception.hpp
std
Definition: Angle.hpp:142
GNSSTK_THROW
#define GNSSTK_THROW(exc)
Definition: Exception.hpp:366
gnsstk::convertCalendarToJD
long convertCalendarToJD(int yy, int mm, int dd)
Definition: TimeConverters.cpp:100
gnsstk::getLeapSeconds
double getLeapSeconds(const int year, const int month, const double day)
Definition: TimeSystem.cpp:53
example6.month
month
Definition: example6.py:65
gnsstk::getTimeSystemCorrection
double getTimeSystemCorrection(const TimeSystem inTS, const TimeSystem outTS, const int year, const int month, const double day)
Definition: TimeSystem.cpp:181


gnsstk
Author(s):
autogenerated on Wed Oct 25 2023 02:40:42