LSST Applications  21.0.0-147-g0e635eb1+1acddb5be5,22.0.0+052faf71bd,22.0.0+1ea9a8b2b2,22.0.0+6312710a6c,22.0.0+729191ecac,22.0.0+7589c3a021,22.0.0+9f079a9461,22.0.1-1-g7d6de66+b8044ec9de,22.0.1-1-g87000a6+536b1ee016,22.0.1-1-g8e32f31+6312710a6c,22.0.1-10-gd060f87+016f7cdc03,22.0.1-12-g9c3108e+df145f6f68,22.0.1-16-g314fa6d+c825727ab8,22.0.1-19-g93a5c75+d23f2fb6d8,22.0.1-19-gb93eaa13+aab3ef7709,22.0.1-2-g8ef0a89+b8044ec9de,22.0.1-2-g92698f7+9f079a9461,22.0.1-2-ga9b0f51+052faf71bd,22.0.1-2-gac51dbf+052faf71bd,22.0.1-2-gb66926d+6312710a6c,22.0.1-2-gcb770ba+09e3807989,22.0.1-20-g32debb5+b8044ec9de,22.0.1-23-gc2439a9a+fb0756638e,22.0.1-3-g496fd5d+09117f784f,22.0.1-3-g59f966b+1e6ba2c031,22.0.1-3-g849a1b8+f8b568069f,22.0.1-3-gaaec9c0+c5c846a8b1,22.0.1-32-g5ddfab5d3+60ce4897b0,22.0.1-4-g037fbe1+64e601228d,22.0.1-4-g8623105+b8044ec9de,22.0.1-5-g096abc9+d18c45d440,22.0.1-5-g15c806e+57f5c03693,22.0.1-7-gba73697+57f5c03693,master-g6e05de7fdc+c1283a92b8,master-g72cdda8301+729191ecac,w.2021.39
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 #include <regex>
41 #include <sstream>
42 
43 #include "boost/format.hpp"
44 
45 #include "lsst/daf/base/DateTime.h"
46 #include "lsst/pex/exceptions.h"
47 
48 namespace dafBase = lsst::daf::base;
49 namespace pexEx = lsst::pex::exceptions;
50 
51 // invalid_nsecs is odr used but has an in-class initializer
52 constexpr long long dafBase::DateTime::invalid_nsecs;
53 
54 // Epoch = 1970 JAN 1 00:00:00 = JD 2440587.5 = MJD 40587.0
55 static double const MJD_TO_JD = 2400000.5;
56 static double const EPOCH_IN_MJD = 40587.0;
57 static double const JD2000 = 2451545.0;
58 
60 static double const NSEC_PER_DAY = 86.4e12;
61 
63 static long long const LL_NSEC_PER_SEC = 1000000000LL;
64 // static long long const LL_NSEC_PER_DAY = 86400 * LL_NSEC_PER_SEC;
65 
66 // Maximum number of days expressible as signed 64-bit nanoseconds.
67 // 2^64 / 2 / 1e9 / 86400
68 // NOTE: long long nsecs will wrap:
69 // -- earliest date representable = sep 21, 1677 00:00:00
70 // -- latest date representable = apr 12, 2262 00:00:00
71 static double const MAX_DAYS = 106751.99;
72 
73 #ifdef CAL_TO_JD
74 static double const HOURS_PER_DAY = 24.0;
75 static double const MIN_PER_DAY = 1440.0;
76 static double const SEC_PER_DAY = 86400.0;
77 #endif
78 
79 // Difference between Terrestrial Time and TAI.
80 static long long const TT_MINUS_TAI_NSECS = 32184000000LL;
81 
82 /* Leap second table as string.
83  *
84  * Source: http://maia.usno.navy.mil/ser7/tai-utc.dat
85  */
86 static std::string leapString =
87  "\
88 1961 JAN 1 =JD 2437300.5 TAI-UTC= 1.4228180 S + (MJD - 37300.) X 0.001296 S\n\
89 1961 AUG 1 =JD 2437512.5 TAI-UTC= 1.3728180 S + (MJD - 37300.) X 0.001296 S\n\
90 1962 JAN 1 =JD 2437665.5 TAI-UTC= 1.8458580 S + (MJD - 37665.) X 0.0011232S\n\
91 1963 NOV 1 =JD 2438334.5 TAI-UTC= 1.9458580 S + (MJD - 37665.) X 0.0011232S\n\
92 1964 JAN 1 =JD 2438395.5 TAI-UTC= 3.2401300 S + (MJD - 38761.) X 0.001296 S\n\
93 1964 APR 1 =JD 2438486.5 TAI-UTC= 3.3401300 S + (MJD - 38761.) X 0.001296 S\n\
94 1964 SEP 1 =JD 2438639.5 TAI-UTC= 3.4401300 S + (MJD - 38761.) X 0.001296 S\n\
95 1965 JAN 1 =JD 2438761.5 TAI-UTC= 3.5401300 S + (MJD - 38761.) X 0.001296 S\n\
96 1965 MAR 1 =JD 2438820.5 TAI-UTC= 3.6401300 S + (MJD - 38761.) X 0.001296 S\n\
97 1965 JUL 1 =JD 2438942.5 TAI-UTC= 3.7401300 S + (MJD - 38761.) X 0.001296 S\n\
98 1965 SEP 1 =JD 2439004.5 TAI-UTC= 3.8401300 S + (MJD - 38761.) X 0.001296 S\n\
99 1966 JAN 1 =JD 2439126.5 TAI-UTC= 4.3131700 S + (MJD - 39126.) X 0.002592 S\n\
100 1968 FEB 1 =JD 2439887.5 TAI-UTC= 4.2131700 S + (MJD - 39126.) X 0.002592 S\n\
101 1972 JAN 1 =JD 2441317.5 TAI-UTC= 10.0 S + (MJD - 41317.) X 0.0 S\n\
102 1972 JUL 1 =JD 2441499.5 TAI-UTC= 11.0 S + (MJD - 41317.) X 0.0 S\n\
103 1973 JAN 1 =JD 2441683.5 TAI-UTC= 12.0 S + (MJD - 41317.) X 0.0 S\n\
104 1974 JAN 1 =JD 2442048.5 TAI-UTC= 13.0 S + (MJD - 41317.) X 0.0 S\n\
105 1975 JAN 1 =JD 2442413.5 TAI-UTC= 14.0 S + (MJD - 41317.) X 0.0 S\n\
106 1976 JAN 1 =JD 2442778.5 TAI-UTC= 15.0 S + (MJD - 41317.) X 0.0 S\n\
107 1977 JAN 1 =JD 2443144.5 TAI-UTC= 16.0 S + (MJD - 41317.) X 0.0 S\n\
108 1978 JAN 1 =JD 2443509.5 TAI-UTC= 17.0 S + (MJD - 41317.) X 0.0 S\n\
109 1979 JAN 1 =JD 2443874.5 TAI-UTC= 18.0 S + (MJD - 41317.) X 0.0 S\n\
110 1980 JAN 1 =JD 2444239.5 TAI-UTC= 19.0 S + (MJD - 41317.) X 0.0 S\n\
111 1981 JUL 1 =JD 2444786.5 TAI-UTC= 20.0 S + (MJD - 41317.) X 0.0 S\n\
112 1982 JUL 1 =JD 2445151.5 TAI-UTC= 21.0 S + (MJD - 41317.) X 0.0 S\n\
113 1983 JUL 1 =JD 2445516.5 TAI-UTC= 22.0 S + (MJD - 41317.) X 0.0 S\n\
114 1985 JUL 1 =JD 2446247.5 TAI-UTC= 23.0 S + (MJD - 41317.) X 0.0 S\n\
115 1988 JAN 1 =JD 2447161.5 TAI-UTC= 24.0 S + (MJD - 41317.) X 0.0 S\n\
116 1990 JAN 1 =JD 2447892.5 TAI-UTC= 25.0 S + (MJD - 41317.) X 0.0 S\n\
117 1991 JAN 1 =JD 2448257.5 TAI-UTC= 26.0 S + (MJD - 41317.) X 0.0 S\n\
118 1992 JUL 1 =JD 2448804.5 TAI-UTC= 27.0 S + (MJD - 41317.) X 0.0 S\n\
119 1993 JUL 1 =JD 2449169.5 TAI-UTC= 28.0 S + (MJD - 41317.) X 0.0 S\n\
120 1994 JUL 1 =JD 2449534.5 TAI-UTC= 29.0 S + (MJD - 41317.) X 0.0 S\n\
121 1996 JAN 1 =JD 2450083.5 TAI-UTC= 30.0 S + (MJD - 41317.) X 0.0 S\n\
122 1997 JUL 1 =JD 2450630.5 TAI-UTC= 31.0 S + (MJD - 41317.) X 0.0 S\n\
123 1999 JAN 1 =JD 2451179.5 TAI-UTC= 32.0 S + (MJD - 41317.) X 0.0 S\n\
124 2006 JAN 1 =JD 2453736.5 TAI-UTC= 33.0 S + (MJD - 41317.) X 0.0 S\n\
125 2009 JAN 1 =JD 2454832.5 TAI-UTC= 34.0 S + (MJD - 41317.) X 0.0 S\n\
126 2012 JUL 1 =JD 2456109.5 TAI-UTC= 35.0 S + (MJD - 41317.) X 0.0 S\n\
127 2015 JUL 1 =JD 2457204.5 TAI-UTC= 36.0 S + (MJD - 41317.) X 0.0 S\n\
128 2017 JAN 1 =JD 2457754.5 TAI-UTC= 37.0 S + (MJD - 41317.) X 0.0 S\n\
129 ";
130 
131 // Anonymous namespace for structures, classes, and formerly file-static
132 // functions.
133 namespace {
134 
136 struct Leap {
137  long long whenUtc;
138  long long whenTai;
139  double offset;
140  double mjdRef;
141  double drift;
142 };
143 
144 class LeapTable : public std::vector<Leap> {
145 public:
146  LeapTable(void);
147 };
148 
149 LeapTable leapSecTable;
150 
151 LeapTable::LeapTable(void) { dafBase::DateTime::initializeLeapSeconds(leapString); }
152 
159 template <typename NsType>
160 NsType utcToTai(NsType nsecs) {
161  size_t i;
162  for (i = 0; i < leapSecTable.size(); ++i) {
163  if (nsecs < leapSecTable[i].whenUtc) break;
164  }
165  if (i == 0) {
166  throw LSST_EXCEPT(
168  (boost::format("DateTime value too early for UTC-TAI conversion: %1%") % nsecs).str());
169  }
170  Leap const& l(leapSecTable[i - 1]);
171  double mjd = static_cast<double>(nsecs) / NSEC_PER_DAY + EPOCH_IN_MJD;
172  double leapSecs = l.offset + (mjd - l.mjdRef) * l.drift;
173  NsType leapNSecs = static_cast<NsType>(leapSecs * 1.0e9 + 0.5);
174  return nsecs + leapNSecs;
175 }
176 
183 template <typename NsType>
184 NsType taiToUtc(NsType nsecs) {
185  size_t i;
186  for (i = 0; i < leapSecTable.size(); ++i) {
187  if (nsecs < leapSecTable[i].whenTai) break;
188  }
189  if (i == 0) {
190  throw LSST_EXCEPT(
192  (boost::format("DateTime value too early for TAI-UTC conversion: %1%") % nsecs).str());
193  }
194  Leap const& l(leapSecTable[i - 1]);
195  double mjd = static_cast<double>(nsecs) / NSEC_PER_DAY + EPOCH_IN_MJD;
196  double leapSecs = l.offset + (mjd - l.mjdRef) * l.drift;
197  // Correct for TAI MJD vs. UTC MJD.
198  leapSecs /= 1.0 + l.drift * 1.0e9 / NSEC_PER_DAY;
199  NsType leapNSecs = static_cast<NsType>(leapSecs * 1.0e9 + 0.5);
200  return nsecs - leapNSecs;
201 }
202 
210 long long nsecAnyToTai(long long nsecs, dafBase::DateTime::Timescale scale) {
211  switch (scale) {
213  return nsecs;
215  return nsecs - TT_MINUS_TAI_NSECS;
217  return utcToTai(nsecs);
218  }
220  os << "Unsupported scale " << scale;
222 }
223 
231 long long nsecTaiToAny(long long nsecs, dafBase::DateTime::Timescale scale) {
232  switch (scale) {
234  return nsecs;
236  return nsecs + TT_MINUS_TAI_NSECS;
238  return taiToUtc(nsecs);
239  }
241  os << "Unsupported scale " << scale;
243 }
244 
245 #ifdef CAL_TO_JD
257 double calendarToJd(int year, int month, int day, int hour, int min, double sec) {
258  if (month <= 2) {
259  year -= 1;
260  month += 12;
261  }
262  int a = int(year / 100);
263  int b = 2 - a + int(a / 4);
264 
265  int yy = 1582, mm = 10; //, d = 4;
266  if (year < yy || (year == yy && month < mm) || (year == yy && month == mm && day <= 4)) {
267  b = 0;
268  }
269 
270  double jd = static_cast<int>(365.25 * (year + 4716)) + static_cast<int>(30.6001 * (month + 1)) + day + b -
271  1524.5;
272  jd += hour / HOURS_PER_DAY + min / MIN_PER_DAY + sec / SEC_PER_DAY;
273 
274  return jd;
275 }
276 
277 #endif // CAL_TO_JD
278 } // end anonymous namespace
279 
280 namespace lsst {
281 namespace daf {
282 namespace base {
283 
284 void DateTime::setNsecsFromMjd(double mjd, Timescale scale) {
285  if (mjd > EPOCH_IN_MJD + MAX_DAYS) {
287  (boost::format("MJD too far in the future: %1%") % mjd).str());
288  }
289  if (mjd < EPOCH_IN_MJD - MAX_DAYS) {
291  (boost::format("MJD too far in the past: %1%") % mjd).str());
292  }
293  _nsecs = nsecAnyToTai(static_cast<long long>((mjd - EPOCH_IN_MJD) * NSEC_PER_DAY), scale);
294 }
295 
296 void DateTime::setNsecsFromJd(double jd, Timescale scale) { setNsecsFromMjd(jd - MJD_TO_JD, scale); }
297 
303 void DateTime::setNsecsFromEpoch(double epoch, Timescale scale) {
304  setNsecsFromMjd(365.25 * (epoch - 2000.0) + JD2000 - MJD_TO_JD, scale);
305 }
306 
307 DateTime::DateTime() : _nsecs(DateTime::invalid_nsecs) {}
308 
309 DateTime::DateTime(long long nsecs, Timescale scale) : _nsecs(nsecAnyToTai(nsecs, scale)) {}
310 
312  switch (system) {
313  case MJD:
314  setNsecsFromMjd(date, scale);
315  break;
316  case JD:
317  setNsecsFromJd(date, scale);
318  break;
319  case EPOCH:
320  setNsecsFromEpoch(date, scale);
321  break;
322  default:
323  throw LSST_EXCEPT(pexEx::InvalidParameterError, "DateSystem must be MJD, JD, or EPOCH");
324  break;
325  }
326 }
327 
328 DateTime::DateTime(int year, int month, int day, int hr, int min, int sec, Timescale scale) {
329  int const minYear = 1902;
330  int const maxYear = 2261;
331  if ((year < minYear) || (year > maxYear)) {
332  throw LSST_EXCEPT(
334  (boost::format("Year = %d out of range [%04d, %04d]") % year % minYear % maxYear).str());
335  }
336 
337  struct tm tm;
338  tm.tm_year = year - 1900;
339  tm.tm_mon = month - 1;
340  tm.tm_mday = day;
341  tm.tm_hour = hr;
342  tm.tm_min = min;
343  tm.tm_sec = sec;
344  tm.tm_wday = 0;
345  tm.tm_yday = 0;
346  tm.tm_isdst = 0;
347  tm.tm_gmtoff = 0;
348 
349  // Convert to seconds since the epoch, correcting to UTC.
350  // Although timegm() is non-standard, it is a commonly-supported
351  // extension and is much safer/more reliable than mktime(3) in that
352  // it doesn't try to deal with the anomalies of local time zones.
353  time_t secs = timegm(&tm);
354 
355  // long long nsecs will blow out beyond 1677-09-21T00:00:00 and 2262-04-12T00:00:00
356  // (refering to the values of EPOCH_IN_MJD +/- MAX_DAYS ... exceeds 64 bits.)
357  // On older machines a tm struct is only 32 bits, and saturates at:
358  // low end - 1901-12-13, 20:45:52
359  // hi end - 2038-01-19, 03:14:07
360  // On newer machines the upper limit is a date in 2262, but the low end is unchanged,
361  // and a unit test will show the problem for dates later than 2038-01-19
362 
363  // timegm returns -1 on error, but the date at unix epoch -1 second also returns a valid value of -1,
364  // so be sure to test for that
365 
366  if (secs == -1) {
367  bool isBad = true; // assume the worst
368  if (year == 1969) {
369  // date may be the one date at which unix sec = -1; try a different year
370  tm.tm_year = 70;
371  if (timegm(&tm) != -1) {
372  isBad = false;
373  }
374  }
375  if (isBad) {
377  (boost::format("Unconvertible date: %04d-%02d-%02dT%02d:%02d:%02d") % year %
378  month % day % hr % min % sec)
379  .str());
380  }
381  }
382 
383  _nsecs = nsecAnyToTai(secs * LL_NSEC_PER_SEC, scale);
384 }
385 
387  std::regex re;
388  if (scale == UTC) {
389  // time zone "Z" required
390  re = std::regex(
391  "(\\d{4})-?(\\d{2})-?(\\d{2})"
392  "T"
393  "(\\d{2}):?(\\d{2}):?(\\d{2})"
394  "([.,](\\d*))?"
395  "Z");
396  } else {
397  // no time zone character accepted
398  re = std::regex(
399  "(\\d{4})-?(\\d{2})-?(\\d{2})"
400  "T"
401  "(\\d{2}):?(\\d{2}):?(\\d{2})"
402  "([.,](\\d*))?");
403  }
404  std::smatch matches;
405  if (!regex_match(iso8601, matches, re)) {
406  throw LSST_EXCEPT(lsst::pex::exceptions::DomainError, "Not in acceptable ISO8601 format: " + iso8601);
407  }
408  // determine TAI nsec truncated to integer seconds
409  // by constructing a DateTime from year, month, day...
410  DateTime dt(atoi(matches.str(1).c_str()), atoi(matches.str(2).c_str()), atoi(matches.str(3).c_str()),
411  atoi(matches.str(4).c_str()), atoi(matches.str(5).c_str()), atoi(matches.str(6).c_str()),
412  scale);
413  _nsecs = dt._nsecs;
414  // add fractional seconds, if any
415  if (matches[7].matched) {
416  std::string frac = matches.str(8);
417  int places = frac.size();
418  if (places > 9) { // truncate fractional nanosec
419  frac.erase(9);
420  }
421  int value = atoi(frac.c_str());
422  while (places < 9) {
423  value *= 10;
424  ++places;
425  }
426  _nsecs += value;
427  }
428 }
429 
430 double DateTime::get(DateSystem system, Timescale scale) const {
431  _assertValid();
432  switch (system) {
433  case MJD:
434  return _getMjd(scale);
435  break;
436  case JD:
437  return _getJd(scale);
438  break;
439  case EPOCH:
440  return _getEpoch(scale);
441  break;
442  default:
443  throw LSST_EXCEPT(pexEx::InvalidParameterError, "DateSystem must be MJD, JD, or EPOCH");
444  break;
445  }
446 }
447 
448 long long DateTime::nsecs(Timescale scale) const {
449  if (!isValid()) {
450  // return the same invalid value for all time scales
452  }
453  return nsecTaiToAny(_nsecs, scale);
454 }
455 
456 double DateTime::_getMjd(Timescale scale) const {
457  _assertValid();
458  double nsecs = nsecTaiToAny(_nsecs, scale);
459  return nsecs / NSEC_PER_DAY + EPOCH_IN_MJD;
460 }
461 
462 double DateTime::_getJd(Timescale scale) const { return _getMjd(scale) + MJD_TO_JD; }
463 
464 double DateTime::_getEpoch(Timescale scale) const { return 2000.0 + (_getJd(scale) - JD2000) / 365.25; }
465 
466 struct tm DateTime::gmtime(Timescale scale) const {
467  _assertValid();
468  struct tm gmt;
469  long long nsecs = nsecTaiToAny(_nsecs, scale);
470  // Round to negative infinity
471  long long frac = nsecs % LL_NSEC_PER_SEC;
472  if (nsecs < 0 && frac < 0) {
473  nsecs -= LL_NSEC_PER_SEC + frac;
474  } else {
475  nsecs -= frac;
476  }
477  time_t secs = static_cast<time_t>(nsecs / LL_NSEC_PER_SEC);
478  gmtime_r(&secs, &gmt);
479  return gmt;
480 }
481 
482 struct timespec DateTime::timespec(Timescale scale) const {
483  _assertValid();
484  struct timespec ts;
485  long long nsecs = nsecTaiToAny(_nsecs, scale);
486  ts.tv_sec = static_cast<time_t>(nsecs / LL_NSEC_PER_SEC);
487  ts.tv_nsec = static_cast<int>(nsecs % LL_NSEC_PER_SEC);
488  return ts;
489 }
490 
491 struct timeval DateTime::timeval(Timescale scale) const {
492  _assertValid();
493  struct timeval tv;
494  long long nsecs = nsecTaiToAny(_nsecs, scale);
495  tv.tv_sec = static_cast<time_t>(nsecs / LL_NSEC_PER_SEC);
496  tv.tv_usec = static_cast<int>((nsecs % LL_NSEC_PER_SEC) / 1000);
497  return tv;
498 }
499 
501  _assertValid();
502  struct tm gmt(this->gmtime(scale));
503 
504  long long fracnsecs = nsecTaiToAny(_nsecs, scale) % LL_NSEC_PER_SEC;
505  if (fracnsecs < 0) {
506  fracnsecs += LL_NSEC_PER_SEC;
507  }
508  auto fmtStr = scale == UTC ? "%04d-%02d-%02dT%02d:%02d:%02d.%09dZ" : "%04d-%02d-%02dT%02d:%02d:%02d.%09d";
509  return (boost::format(fmtStr) % (gmt.tm_year + 1900) % (gmt.tm_mon + 1) % gmt.tm_mday % gmt.tm_hour %
510  gmt.tm_min % gmt.tm_sec % fracnsecs)
511  .str();
512 }
513 
514 bool DateTime::operator==(DateTime const& rhs) const { return _nsecs == rhs._nsecs; }
515 
516 std::size_t DateTime::hash_value() const noexcept { return std::hash<long long>()(_nsecs); }
517 
519  struct timeval tv;
520  int ret = gettimeofday(&tv, 0);
521  if (ret != 0) {
522  throw LSST_EXCEPT(lsst::pex::exceptions::RuntimeError, "Unable to get current time");
523  }
524  long long nsecs = tv.tv_sec * LL_NSEC_PER_SEC + tv.tv_usec * 1000LL;
525  return DateTime(nsecs, DateTime::UTC);
526 }
527 
529  Leap l;
530  leapSecTable.clear();
531  std::regex re(
532  "\\d{4}.*?=JD\\s*([\\d.]+)\\s+TAI-UTC=\\s+([\\d.]+)\\s+S"
533  " \\+ \\(MJD - ([\\d.]+)\\) X ([\\d.]+)\\s*S");
534 
535 
536  for (std::sregex_iterator i = std::sregex_iterator(leapString.begin(), leapString.end(), re);
537  i != std::sregex_iterator(); ++i) {
538  double mjdUtc = std::stod((*i)[1]) - MJD_TO_JD;
539  l.offset = std::stod((*i)[2]);
540  l.mjdRef = std::stod((*i)[3]);
541  l.drift = std::stod((*i)[4]);
542  l.whenUtc = static_cast<long long>((mjdUtc - EPOCH_IN_MJD) * NSEC_PER_DAY);
543  l.whenTai = l.whenUtc + static_cast<long long>(1.0e9 * (l.offset + (mjdUtc - l.mjdRef) * l.drift));
544  leapSecTable.push_back(l);
545  }
546 }
547 
548 } // namespace base
549 } // namespace daf
550 } // 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:557
table::Key< int > b
table::Key< int > a
T begin(T... args)
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:307
std::size_t hash_value() const noexcept
Return a hash of this object.
Definition: DateTime.cc:516
std::string toString(Timescale scale) const
Get date as an ISO8601-formatted string.
Definition: DateTime.cc:500
bool isValid() const
Is this date valid?
Definition: DateTime.h:203
static DateTime now(void)
Return current time as a DateTime.
Definition: DateTime.cc:518
double get(DateSystem system=MJD, Timescale scale=TAI) const
Get date as a double in a specified representation, such as MJD.
Definition: DateTime.cc:430
struct timeval timeval(Timescale scale) const
Get date as a timeval struct, with time in seconds and microseconds.
Definition: DateTime.cc:491
struct tm gmtime(Timescale scale) const
Get date as a tm struct, with truncated fractional seconds.
Definition: DateTime.cc:466
static void initializeLeapSeconds(std::string const &leapString)
Initialize the leap second table from USNO.
Definition: DateTime.cc:528
bool operator==(DateTime const &rhs) const
Definition: DateTime.cc:514
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:448
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 end(T... args)
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)
T stod(T... args)
T str(T... args)