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