LSST Applications  21.0.0+04719a4bac,21.0.0-1-ga51b5d4+f5e6047307,21.0.0-11-g2b59f77+a9c1acf22d,21.0.0-11-ga42c5b2+86977b0b17,21.0.0-12-gf4ce030+76814010d2,21.0.0-13-g1721dae+760e7a6536,21.0.0-13-g3a573fe+768d78a30a,21.0.0-15-g5a7caf0+f21cbc5713,21.0.0-16-g0fb55c1+b60e2d390c,21.0.0-19-g4cded4ca+71a93a33c0,21.0.0-2-g103fe59+bb20972958,21.0.0-2-g45278ab+04719a4bac,21.0.0-2-g5242d73+3ad5d60fb1,21.0.0-2-g7f82c8f+8babb168e8,21.0.0-2-g8f08a60+06509c8b61,21.0.0-2-g8faa9b5+616205b9df,21.0.0-2-ga326454+8babb168e8,21.0.0-2-gde069b7+5e4aea9c2f,21.0.0-2-gecfae73+1d3a86e577,21.0.0-2-gfc62afb+3ad5d60fb1,21.0.0-25-g1d57be3cd+e73869a214,21.0.0-3-g357aad2+ed88757d29,21.0.0-3-g4a4ce7f+3ad5d60fb1,21.0.0-3-g4be5c26+3ad5d60fb1,21.0.0-3-g65f322c+e0b24896a3,21.0.0-3-g7d9da8d+616205b9df,21.0.0-3-ge02ed75+a9c1acf22d,21.0.0-4-g591bb35+a9c1acf22d,21.0.0-4-g65b4814+b60e2d390c,21.0.0-4-gccdca77+0de219a2bc,21.0.0-4-ge8a399c+6c55c39e83,21.0.0-5-gd00fb1e+05fce91b99,21.0.0-6-gc675373+3ad5d60fb1,21.0.0-64-g1122c245+4fb2b8f86e,21.0.0-7-g04766d7+cd19d05db2,21.0.0-7-gdf92d54+04719a4bac,21.0.0-8-g5674e7b+d1bd76f71f,master-gac4afde19b+a9c1acf22d,w.2021.13
LSST Data Management Base Package
DateTime.cc
Go to the documentation of this file.
1 // -*- lsst-c++ -*-
2 
3 /*
4  * LSST Data Management System
5  * Copyright 2008, 2009, 2010 LSST Corporation.
6  *
7  * This product includes software developed by the
8  * LSST Project (http://www.lsst.org/).
9  *
10  * This program is free software: you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation, either version 3 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the LSST License Statement and
21  * the GNU General Public License along with this program. If not,
22  * see <http://www.lsstcorp.org/LegalNotices/>.
23  */
24 
37 #include <limits>
38 #include <cmath>
39 #include <vector>
40 
41 #include "boost/format.hpp"
42 #include "boost/regex.hpp"
43 
44 #include "lsst/daf/base/DateTime.h"
45 #include "lsst/pex/exceptions.h"
46 
47 namespace dafBase = lsst::daf::base;
48 namespace pexEx = lsst::pex::exceptions;
49 
50 // invalid_nsecs is odr used but has an in-class initializer
51 constexpr long long dafBase::DateTime::invalid_nsecs;
52 
53 // Epoch = 1970 JAN 1 00:00:00 = JD 2440587.5 = MJD 40587.0
54 static double const MJD_TO_JD = 2400000.5;
55 static double const EPOCH_IN_MJD = 40587.0;
56 static double const JD2000 = 2451544.50;
57 
59 static double const NSEC_PER_DAY = 86.4e12;
60 
62 static long long const LL_NSEC_PER_SEC = 1000000000LL;
63 // static long long const LL_NSEC_PER_DAY = 86400 * LL_NSEC_PER_SEC;
64 
65 // Maximum number of days expressible as signed 64-bit nanoseconds.
66 // 2^64 / 2 / 1e9 / 86400
67 // NOTE: long long nsecs will wrap:
68 // -- earliest date representable = sep 21, 1677 00:00:00
69 // -- latest date representable = apr 12, 2262 00:00:00
70 static double const MAX_DAYS = 106751.99;
71 
72 #ifdef CAL_TO_JD
73 static double const HOURS_PER_DAY = 24.0;
74 static double const MIN_PER_DAY = 1440.0;
75 static double const SEC_PER_DAY = 86400.0;
76 #endif
77 
78 // Difference between Terrestrial Time and TAI.
79 static long long const TT_MINUS_TAI_NSECS = 32184000000LL;
80 
81 /* Leap second table as string.
82  *
83  * Source: http://maia.usno.navy.mil/ser7/tai-utc.dat
84  */
85 static std::string leapString =
86  "\
87 1961 JAN 1 =JD 2437300.5 TAI-UTC= 1.4228180 S + (MJD - 37300.) X 0.001296 S\n\
88 1961 AUG 1 =JD 2437512.5 TAI-UTC= 1.3728180 S + (MJD - 37300.) X 0.001296 S\n\
89 1962 JAN 1 =JD 2437665.5 TAI-UTC= 1.8458580 S + (MJD - 37665.) X 0.0011232S\n\
90 1963 NOV 1 =JD 2438334.5 TAI-UTC= 1.9458580 S + (MJD - 37665.) X 0.0011232S\n\
91 1964 JAN 1 =JD 2438395.5 TAI-UTC= 3.2401300 S + (MJD - 38761.) X 0.001296 S\n\
92 1964 APR 1 =JD 2438486.5 TAI-UTC= 3.3401300 S + (MJD - 38761.) X 0.001296 S\n\
93 1964 SEP 1 =JD 2438639.5 TAI-UTC= 3.4401300 S + (MJD - 38761.) X 0.001296 S\n\
94 1965 JAN 1 =JD 2438761.5 TAI-UTC= 3.5401300 S + (MJD - 38761.) X 0.001296 S\n\
95 1965 MAR 1 =JD 2438820.5 TAI-UTC= 3.6401300 S + (MJD - 38761.) X 0.001296 S\n\
96 1965 JUL 1 =JD 2438942.5 TAI-UTC= 3.7401300 S + (MJD - 38761.) X 0.001296 S\n\
97 1965 SEP 1 =JD 2439004.5 TAI-UTC= 3.8401300 S + (MJD - 38761.) X 0.001296 S\n\
98 1966 JAN 1 =JD 2439126.5 TAI-UTC= 4.3131700 S + (MJD - 39126.) X 0.002592 S\n\
99 1968 FEB 1 =JD 2439887.5 TAI-UTC= 4.2131700 S + (MJD - 39126.) X 0.002592 S\n\
100 1972 JAN 1 =JD 2441317.5 TAI-UTC= 10.0 S + (MJD - 41317.) X 0.0 S\n\
101 1972 JUL 1 =JD 2441499.5 TAI-UTC= 11.0 S + (MJD - 41317.) X 0.0 S\n\
102 1973 JAN 1 =JD 2441683.5 TAI-UTC= 12.0 S + (MJD - 41317.) X 0.0 S\n\
103 1974 JAN 1 =JD 2442048.5 TAI-UTC= 13.0 S + (MJD - 41317.) X 0.0 S\n\
104 1975 JAN 1 =JD 2442413.5 TAI-UTC= 14.0 S + (MJD - 41317.) X 0.0 S\n\
105 1976 JAN 1 =JD 2442778.5 TAI-UTC= 15.0 S + (MJD - 41317.) X 0.0 S\n\
106 1977 JAN 1 =JD 2443144.5 TAI-UTC= 16.0 S + (MJD - 41317.) X 0.0 S\n\
107 1978 JAN 1 =JD 2443509.5 TAI-UTC= 17.0 S + (MJD - 41317.) X 0.0 S\n\
108 1979 JAN 1 =JD 2443874.5 TAI-UTC= 18.0 S + (MJD - 41317.) X 0.0 S\n\
109 1980 JAN 1 =JD 2444239.5 TAI-UTC= 19.0 S + (MJD - 41317.) X 0.0 S\n\
110 1981 JUL 1 =JD 2444786.5 TAI-UTC= 20.0 S + (MJD - 41317.) X 0.0 S\n\
111 1982 JUL 1 =JD 2445151.5 TAI-UTC= 21.0 S + (MJD - 41317.) X 0.0 S\n\
112 1983 JUL 1 =JD 2445516.5 TAI-UTC= 22.0 S + (MJD - 41317.) X 0.0 S\n\
113 1985 JUL 1 =JD 2446247.5 TAI-UTC= 23.0 S + (MJD - 41317.) X 0.0 S\n\
114 1988 JAN 1 =JD 2447161.5 TAI-UTC= 24.0 S + (MJD - 41317.) X 0.0 S\n\
115 1990 JAN 1 =JD 2447892.5 TAI-UTC= 25.0 S + (MJD - 41317.) X 0.0 S\n\
116 1991 JAN 1 =JD 2448257.5 TAI-UTC= 26.0 S + (MJD - 41317.) X 0.0 S\n\
117 1992 JUL 1 =JD 2448804.5 TAI-UTC= 27.0 S + (MJD - 41317.) X 0.0 S\n\
118 1993 JUL 1 =JD 2449169.5 TAI-UTC= 28.0 S + (MJD - 41317.) X 0.0 S\n\
119 1994 JUL 1 =JD 2449534.5 TAI-UTC= 29.0 S + (MJD - 41317.) X 0.0 S\n\
120 1996 JAN 1 =JD 2450083.5 TAI-UTC= 30.0 S + (MJD - 41317.) X 0.0 S\n\
121 1997 JUL 1 =JD 2450630.5 TAI-UTC= 31.0 S + (MJD - 41317.) X 0.0 S\n\
122 1999 JAN 1 =JD 2451179.5 TAI-UTC= 32.0 S + (MJD - 41317.) X 0.0 S\n\
123 2006 JAN 1 =JD 2453736.5 TAI-UTC= 33.0 S + (MJD - 41317.) X 0.0 S\n\
124 2009 JAN 1 =JD 2454832.5 TAI-UTC= 34.0 S + (MJD - 41317.) X 0.0 S\n\
125 2012 JUL 1 =JD 2456109.5 TAI-UTC= 35.0 S + (MJD - 41317.) X 0.0 S\n\
126 2015 JUL 1 =JD 2457204.5 TAI-UTC= 36.0 S + (MJD - 41317.) X 0.0 S\n\
127 2017 JAN 1 =JD 2457754.5 TAI-UTC= 37.0 S + (MJD - 41317.) X 0.0 S\n\
128 ";
129 
130 // Anonymous namespace for structures, classes, and formerly file-static
131 // functions.
132 namespace {
133 
135 struct Leap {
136  long long whenUtc;
137  long long whenTai;
138  double offset;
139  double mjdRef;
140  double drift;
141 };
142 
143 class LeapTable : public std::vector<Leap> {
144 public:
145  LeapTable(void);
146 };
147 
148 LeapTable leapSecTable;
149 
150 LeapTable::LeapTable(void) { dafBase::DateTime::initializeLeapSeconds(leapString); }
151 
158 template <typename NsType>
159 NsType utcToTai(NsType nsecs) {
160  size_t i;
161  for (i = 0; i < leapSecTable.size(); ++i) {
162  if (nsecs < leapSecTable[i].whenUtc) break;
163  }
164  if (i == 0) {
165  throw LSST_EXCEPT(
167  (boost::format("DateTime value too early for UTC-TAI conversion: %1%") % nsecs).str());
168  }
169  Leap const& l(leapSecTable[i - 1]);
170  double mjd = static_cast<double>(nsecs) / NSEC_PER_DAY + EPOCH_IN_MJD;
171  double leapSecs = l.offset + (mjd - l.mjdRef) * l.drift;
172  NsType leapNSecs = static_cast<NsType>(leapSecs * 1.0e9 + 0.5);
173  return nsecs + leapNSecs;
174 }
175 
182 template <typename NsType>
183 NsType taiToUtc(NsType nsecs) {
184  size_t i;
185  for (i = 0; i < leapSecTable.size(); ++i) {
186  if (nsecs < leapSecTable[i].whenTai) break;
187  }
188  if (i == 0) {
189  throw LSST_EXCEPT(
191  (boost::format("DateTime value too early for TAI-UTC conversion: %1%") % nsecs).str());
192  }
193  Leap const& l(leapSecTable[i - 1]);
194  double mjd = static_cast<double>(nsecs) / NSEC_PER_DAY + EPOCH_IN_MJD;
195  double leapSecs = l.offset + (mjd - l.mjdRef) * l.drift;
196  // Correct for TAI MJD vs. UTC MJD.
197  leapSecs /= 1.0 + l.drift * 1.0e9 / NSEC_PER_DAY;
198  NsType leapNSecs = static_cast<NsType>(leapSecs * 1.0e9 + 0.5);
199  return nsecs - leapNSecs;
200 }
201 
209 long long nsecAnyToTai(long long nsecs, dafBase::DateTime::Timescale scale) {
210  switch (scale) {
212  return nsecs;
214  return nsecs - TT_MINUS_TAI_NSECS;
216  return utcToTai(nsecs);
217  }
219  os << "Unsupported scale " << scale;
221 }
222 
230 long long nsecTaiToAny(long long nsecs, dafBase::DateTime::Timescale scale) {
231  switch (scale) {
233  return nsecs;
235  return nsecs + TT_MINUS_TAI_NSECS;
237  return taiToUtc(nsecs);
238  }
240  os << "Unsupported scale " << scale;
242 }
243 
244 #ifdef CAL_TO_JD
256 double calendarToJd(int year, int month, int day, int hour, int min, double sec) {
257  if (month <= 2) {
258  year -= 1;
259  month += 12;
260  }
261  int a = int(year / 100);
262  int b = 2 - a + int(a / 4);
263 
264  int yy = 1582, mm = 10; //, d = 4;
265  if (year < yy || (year == yy && month < mm) || (year == yy && month == mm && day <= 4)) {
266  b = 0;
267  }
268 
269  double jd = static_cast<int>(365.25 * (year + 4716)) + static_cast<int>(30.6001 * (month + 1)) + day + b -
270  1524.5;
271  jd += hour / HOURS_PER_DAY + min / MIN_PER_DAY + sec / SEC_PER_DAY;
272 
273  return jd;
274 }
275 
276 #endif // CAL_TO_JD
277 } // end anonymous namespace
278 
279 namespace lsst {
280 namespace daf {
281 namespace base {
282 
283 void DateTime::setNsecsFromMjd(double mjd, Timescale scale) {
284  if (mjd > EPOCH_IN_MJD + MAX_DAYS) {
286  (boost::format("MJD too far in the future: %1%") % mjd).str());
287  }
288  if (mjd < EPOCH_IN_MJD - MAX_DAYS) {
290  (boost::format("MJD too far in the past: %1%") % mjd).str());
291  }
292  _nsecs = nsecAnyToTai(static_cast<long long>((mjd - EPOCH_IN_MJD) * NSEC_PER_DAY), scale);
293 }
294 
295 void DateTime::setNsecsFromJd(double jd, Timescale scale) { setNsecsFromMjd(jd - MJD_TO_JD, scale); }
296 
302 void DateTime::setNsecsFromEpoch(double epoch, Timescale scale) {
303  setNsecsFromMjd(365.25 * (epoch - 2000.0) + JD2000 - MJD_TO_JD, scale);
304 }
305 
306 DateTime::DateTime() : _nsecs(DateTime::invalid_nsecs) {}
307 
308 DateTime::DateTime(long long nsecs, Timescale scale) : _nsecs(nsecAnyToTai(nsecs, scale)) {}
309 
311  switch (system) {
312  case MJD:
313  setNsecsFromMjd(date, scale);
314  break;
315  case JD:
316  setNsecsFromJd(date, scale);
317  break;
318  case EPOCH:
319  setNsecsFromEpoch(date, scale);
320  break;
321  default:
322  throw LSST_EXCEPT(pexEx::InvalidParameterError, "DateSystem must be MJD, JD, or EPOCH");
323  break;
324  }
325 }
326 
327 DateTime::DateTime(int year, int month, int day, int hr, int min, int sec, Timescale scale) {
328  int const minYear = 1902;
329  int const maxYear = 2261;
330  if ((year < minYear) || (year > maxYear)) {
331  throw LSST_EXCEPT(
333  (boost::format("Year = %d out of range [%04d, %04d]") % year % minYear % maxYear).str());
334  }
335 
336  struct tm tm;
337  tm.tm_year = year - 1900;
338  tm.tm_mon = month - 1;
339  tm.tm_mday = day;
340  tm.tm_hour = hr;
341  tm.tm_min = min;
342  tm.tm_sec = sec;
343  tm.tm_wday = 0;
344  tm.tm_yday = 0;
345  tm.tm_isdst = 0;
346  tm.tm_gmtoff = 0;
347 
348  // Convert to seconds since the epoch, correcting to UTC.
349  // Although timegm() is non-standard, it is a commonly-supported
350  // extension and is much safer/more reliable than mktime(3) in that
351  // it doesn't try to deal with the anomalies of local time zones.
352  time_t secs = timegm(&tm);
353 
354  // long long nsecs will blow out beyond 1677-09-21T00:00:00 and 2262-04-12T00:00:00
355  // (refering to the values of EPOCH_IN_MJD +/- MAX_DAYS ... exceeds 64 bits.)
356  // On older machines a tm struct is only 32 bits, and saturates at:
357  // low end - 1901-12-13, 20:45:52
358  // hi end - 2038-01-19, 03:14:07
359  // On newer machines the upper limit is a date in 2262, but the low end is unchanged,
360  // and a unit test will show the problem for dates later than 2038-01-19
361 
362  // timegm returns -1 on error, but the date at unix epoch -1 second also returns a valid value of -1,
363  // so be sure to test for that
364 
365  if (secs == -1) {
366  bool isBad = true; // assume the worst
367  if (year == 1969) {
368  // date may be the one date at which unix sec = -1; try a different year
369  tm.tm_year = 70;
370  if (timegm(&tm) != -1) {
371  isBad = false;
372  }
373  }
374  if (isBad) {
376  (boost::format("Unconvertible date: %04d-%02d-%02dT%02d:%02d:%02d") % year %
377  month % day % hr % min % sec)
378  .str());
379  }
380  }
381 
382  _nsecs = nsecAnyToTai(secs * LL_NSEC_PER_SEC, scale);
383 }
384 
386  boost::regex re;
387  if (scale == UTC) {
388  // time zone "Z" required
389  re = boost::regex(
390  "(\\d{4})-?(\\d{2})-?(\\d{2})"
391  "T"
392  "(\\d{2}):?(\\d{2}):?(\\d{2})"
393  "([.,](\\d*))?"
394  "Z");
395  } else {
396  // no time zone character accepted
397  re = boost::regex(
398  "(\\d{4})-?(\\d{2})-?(\\d{2})"
399  "T"
400  "(\\d{2}):?(\\d{2}):?(\\d{2})"
401  "([.,](\\d*))?");
402  }
403  boost::smatch matches;
404  if (!regex_match(iso8601, matches, re)) {
405  throw LSST_EXCEPT(lsst::pex::exceptions::DomainError, "Not in acceptable ISO8601 format: " + iso8601);
406  }
407  // determine TAI nsec truncated to integer seconds
408  // by constructing a DateTime from year, month, day...
409  DateTime dt(atoi(matches.str(1).c_str()), atoi(matches.str(2).c_str()), atoi(matches.str(3).c_str()),
410  atoi(matches.str(4).c_str()), atoi(matches.str(5).c_str()), atoi(matches.str(6).c_str()),
411  scale);
412  _nsecs = dt._nsecs;
413  // add fractional seconds, if any
414  if (matches[7].matched) {
415  std::string frac = matches.str(8);
416  int places = frac.size();
417  if (places > 9) { // truncate fractional nanosec
418  frac.erase(9);
419  }
420  int value = atoi(frac.c_str());
421  while (places < 9) {
422  value *= 10;
423  ++places;
424  }
425  _nsecs += value;
426  }
427 }
428 
429 double DateTime::get(DateSystem system, Timescale scale) const {
430  _assertValid();
431  switch (system) {
432  case MJD:
433  return _getMjd(scale);
434  break;
435  case JD:
436  return _getJd(scale);
437  break;
438  case EPOCH:
439  return _getEpoch(scale);
440  break;
441  default:
442  throw LSST_EXCEPT(pexEx::InvalidParameterError, "DateSystem must be MJD, JD, or EPOCH");
443  break;
444  }
445 }
446 
447 long long DateTime::nsecs(Timescale scale) const {
448  if (!isValid()) {
449  // return the same invalid value for all time scales
451  }
452  return nsecTaiToAny(_nsecs, scale);
453 }
454 
455 double DateTime::_getMjd(Timescale scale) const {
456  _assertValid();
457  double nsecs = nsecTaiToAny(_nsecs, scale);
458  return nsecs / NSEC_PER_DAY + EPOCH_IN_MJD;
459 }
460 
461 double DateTime::_getJd(Timescale scale) const { return _getMjd(scale) + MJD_TO_JD; }
462 
463 double DateTime::_getEpoch(Timescale scale) const { return 2000.0 + (_getJd(scale) - JD2000) / 365.25; }
464 
465 struct tm DateTime::gmtime(Timescale scale) const {
466  _assertValid();
467  struct tm gmt;
468  long long nsecs = nsecTaiToAny(_nsecs, scale);
469  // Round to negative infinity
470  long long frac = nsecs % LL_NSEC_PER_SEC;
471  if (nsecs < 0 && frac < 0) {
472  nsecs -= LL_NSEC_PER_SEC + frac;
473  } else {
474  nsecs -= frac;
475  }
476  time_t secs = static_cast<time_t>(nsecs / LL_NSEC_PER_SEC);
477  gmtime_r(&secs, &gmt);
478  return gmt;
479 }
480 
481 struct timespec DateTime::timespec(Timescale scale) const {
482  _assertValid();
483  struct timespec ts;
484  long long nsecs = nsecTaiToAny(_nsecs, scale);
485  ts.tv_sec = static_cast<time_t>(nsecs / LL_NSEC_PER_SEC);
486  ts.tv_nsec = static_cast<int>(nsecs % LL_NSEC_PER_SEC);
487  return ts;
488 }
489 
490 struct timeval DateTime::timeval(Timescale scale) const {
491  _assertValid();
492  struct timeval tv;
493  long long nsecs = nsecTaiToAny(_nsecs, scale);
494  tv.tv_sec = static_cast<time_t>(nsecs / LL_NSEC_PER_SEC);
495  tv.tv_usec = static_cast<int>((nsecs % LL_NSEC_PER_SEC) / 1000);
496  return tv;
497 }
498 
500  _assertValid();
501  struct tm gmt(this->gmtime(scale));
502 
503  long long fracnsecs = nsecTaiToAny(_nsecs, scale) % LL_NSEC_PER_SEC;
504  if (fracnsecs < 0) {
505  fracnsecs += LL_NSEC_PER_SEC;
506  }
507  auto fmtStr = scale == UTC ? "%04d-%02d-%02dT%02d:%02d:%02d.%09dZ" : "%04d-%02d-%02dT%02d:%02d:%02d.%09d";
508  return (boost::format(fmtStr) % (gmt.tm_year + 1900) % (gmt.tm_mon + 1) % gmt.tm_mday % gmt.tm_hour %
509  gmt.tm_min % gmt.tm_sec % fracnsecs)
510  .str();
511 }
512 
513 bool DateTime::operator==(DateTime const& rhs) const { return _nsecs == rhs._nsecs; }
514 
515 std::size_t DateTime::hash_value() const noexcept { return std::hash<long long>()(_nsecs); }
516 
518  struct timeval tv;
519  int ret = gettimeofday(&tv, 0);
520  if (ret != 0) {
521  throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError, "Unable to get current time");
522  }
523  long long nsecs = tv.tv_sec * LL_NSEC_PER_SEC + tv.tv_usec * 1000LL;
524  return DateTime(nsecs, DateTime::UTC);
525 }
526 
528  Leap l;
529  leapSecTable.clear();
530  boost::regex re(
531  "^\\d{4}.*?=JD\\s*([\\d.]+)\\s+TAI-UTC=\\s+([\\d.]+)\\s+S"
532  " \\+ \\(MJD - ([\\d.]+)\\) X ([\\d.]+)\\s*S$");
533  for (boost::cregex_iterator i = make_regex_iterator(leapString.c_str(), re);
534  i != boost::cregex_iterator(); ++i) {
535  double mjdUtc = strtod((*i)[1].first, 0) - MJD_TO_JD;
536  l.offset = strtod((*i)[2].first, 0);
537  l.mjdRef = strtod((*i)[3].first, 0);
538  l.drift = strtod((*i)[4].first, 0);
539  l.whenUtc = static_cast<long long>((mjdUtc - EPOCH_IN_MJD) * NSEC_PER_DAY);
540  l.whenTai = l.whenUtc + static_cast<long long>(1.0e9 * (l.offset + (mjdUtc - l.mjdRef) * l.drift));
541  leapSecTable.push_back(l);
542  }
543 }
544 
545 } // namespace base
546 } // namespace daf
547 } // namespace lsst
int min
Interface for DateTime class.
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
Definition: Exception.h:48
std::ostream * os
Definition: Schema.cc:746
table::Key< int > b
table::Key< int > a
T c_str(T... args)
Class for handling dates/times, including MJD, UTC, and TAI.
Definition: DateTime.h:64
DateTime()
Default constructor: construct an invalid DateTime.
Definition: DateTime.cc:306
std::size_t hash_value() const noexcept
Return a hash of this object.
Definition: DateTime.cc:515
std::string toString(Timescale scale) const
Get date as an ISO8601-formatted string.
Definition: DateTime.cc:499
bool isValid() const
Is this date valid?
Definition: DateTime.h:203
static DateTime now(void)
Return current time as a DateTime.
Definition: DateTime.cc:517
double get(DateSystem system=MJD, Timescale scale=TAI) const
Get date as a double in a specified representation, such as MJD.
Definition: DateTime.cc:429
struct timeval timeval(Timescale scale) const
Get date as a timeval struct, with time in seconds and microseconds.
Definition: DateTime.cc:490
struct tm gmtime(Timescale scale) const
Get date as a tm struct, with truncated fractional seconds.
Definition: DateTime.cc:465
static void initializeLeapSeconds(std::string const &leapString)
Initialize the leap second table from USNO.
Definition: DateTime.cc:527
bool operator==(DateTime const &rhs) const
Definition: DateTime.cc:513
constexpr static long long invalid_nsecs
Definition: DateTime.h:75
long long nsecs(Timescale scale=TAI) const
Get date as nanoseconds since the unix epoch.
Definition: DateTime.cc:447
Reports arguments outside the domain of an operation.
Definition: Runtime.h:57
Reports invalid arguments.
Definition: Runtime.h:66
Reports errors that are due to events beyond the control of the program.
Definition: Runtime.h:104
T erase(T... args)
def scale(algorithm, min, max=None, frame=None)
Definition: ds9.py:108
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
Definition: history.py:174
A base class for image defects.
T size(T... args)