LSST Applications g070148d5b3+33e5256705,g0d53e28543+25c8b88941,g0da5cf3356+2dd1178308,g1081da9e2a+62d12e78cb,g17e5ecfddb+7e422d6136,g1c76d35bf8+ede3a706f7,g295839609d+225697d880,g2e2c1a68ba+cc1f6f037e,g2ffcdf413f+853cd4dcde,g38293774b4+62d12e78cb,g3b44f30a73+d953f1ac34,g48ccf36440+885b902d19,g4b2f1765b6+7dedbde6d2,g5320a0a9f6+0c5d6105b6,g56b687f8c9+ede3a706f7,g5c4744a4d9+ef6ac23297,g5ffd174ac0+0c5d6105b6,g6075d09f38+66af417445,g667d525e37+2ced63db88,g670421136f+2ced63db88,g71f27ac40c+2ced63db88,g774830318a+463cbe8d1f,g7876bc68e5+1d137996f1,g7985c39107+62d12e78cb,g7fdac2220c+0fd8241c05,g96f01af41f+368e6903a7,g9ca82378b8+2ced63db88,g9d27549199+ef6ac23297,gabe93b2c52+e3573e3735,gb065e2a02a+3dfbe639da,gbc3249ced9+0c5d6105b6,gbec6a3398f+0c5d6105b6,gc9534b9d65+35b9f25267,gd01420fc67+0c5d6105b6,geee7ff78d7+a14128c129,gf63283c776+ede3a706f7,gfed783d017+0c5d6105b6,w.2022.47
LSST Data Management Base Package
Loading...
Searching...
No Matches
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
46#include "lsst/pex/exceptions.h"
47
48namespace dafBase = lsst::daf::base;
50
51// invalid_nsecs is odr used but has an in-class initializer
52constexpr long long dafBase::DateTime::invalid_nsecs;
53
54// Epoch = 1970 JAN 1 00:00:00 = JD 2440587.5 = MJD 40587.0
55static double const MJD_TO_JD = 2400000.5;
56static double const EPOCH_IN_MJD = 40587.0;
57static double const JD2000 = 2451545.0;
58
60static double const NSEC_PER_DAY = 86.4e12;
61
63static 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
71static double const MAX_DAYS = 106751.99;
72
73#ifdef CAL_TO_JD
74static double const HOURS_PER_DAY = 24.0;
75static double const MIN_PER_DAY = 1440.0;
76static double const SEC_PER_DAY = 86400.0;
77#endif
78
79// Difference between Terrestrial Time and TAI.
80static 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 */
86static std::string leapString =
87 "\
881961 JAN 1 =JD 2437300.5 TAI-UTC= 1.4228180 S + (MJD - 37300.) X 0.001296 S\n\
891961 AUG 1 =JD 2437512.5 TAI-UTC= 1.3728180 S + (MJD - 37300.) X 0.001296 S\n\
901962 JAN 1 =JD 2437665.5 TAI-UTC= 1.8458580 S + (MJD - 37665.) X 0.0011232S\n\
911963 NOV 1 =JD 2438334.5 TAI-UTC= 1.9458580 S + (MJD - 37665.) X 0.0011232S\n\
921964 JAN 1 =JD 2438395.5 TAI-UTC= 3.2401300 S + (MJD - 38761.) X 0.001296 S\n\
931964 APR 1 =JD 2438486.5 TAI-UTC= 3.3401300 S + (MJD - 38761.) X 0.001296 S\n\
941964 SEP 1 =JD 2438639.5 TAI-UTC= 3.4401300 S + (MJD - 38761.) X 0.001296 S\n\
951965 JAN 1 =JD 2438761.5 TAI-UTC= 3.5401300 S + (MJD - 38761.) X 0.001296 S\n\
961965 MAR 1 =JD 2438820.5 TAI-UTC= 3.6401300 S + (MJD - 38761.) X 0.001296 S\n\
971965 JUL 1 =JD 2438942.5 TAI-UTC= 3.7401300 S + (MJD - 38761.) X 0.001296 S\n\
981965 SEP 1 =JD 2439004.5 TAI-UTC= 3.8401300 S + (MJD - 38761.) X 0.001296 S\n\
991966 JAN 1 =JD 2439126.5 TAI-UTC= 4.3131700 S + (MJD - 39126.) X 0.002592 S\n\
1001968 FEB 1 =JD 2439887.5 TAI-UTC= 4.2131700 S + (MJD - 39126.) X 0.002592 S\n\
1011972 JAN 1 =JD 2441317.5 TAI-UTC= 10.0 S + (MJD - 41317.) X 0.0 S\n\
1021972 JUL 1 =JD 2441499.5 TAI-UTC= 11.0 S + (MJD - 41317.) X 0.0 S\n\
1031973 JAN 1 =JD 2441683.5 TAI-UTC= 12.0 S + (MJD - 41317.) X 0.0 S\n\
1041974 JAN 1 =JD 2442048.5 TAI-UTC= 13.0 S + (MJD - 41317.) X 0.0 S\n\
1051975 JAN 1 =JD 2442413.5 TAI-UTC= 14.0 S + (MJD - 41317.) X 0.0 S\n\
1061976 JAN 1 =JD 2442778.5 TAI-UTC= 15.0 S + (MJD - 41317.) X 0.0 S\n\
1071977 JAN 1 =JD 2443144.5 TAI-UTC= 16.0 S + (MJD - 41317.) X 0.0 S\n\
1081978 JAN 1 =JD 2443509.5 TAI-UTC= 17.0 S + (MJD - 41317.) X 0.0 S\n\
1091979 JAN 1 =JD 2443874.5 TAI-UTC= 18.0 S + (MJD - 41317.) X 0.0 S\n\
1101980 JAN 1 =JD 2444239.5 TAI-UTC= 19.0 S + (MJD - 41317.) X 0.0 S\n\
1111981 JUL 1 =JD 2444786.5 TAI-UTC= 20.0 S + (MJD - 41317.) X 0.0 S\n\
1121982 JUL 1 =JD 2445151.5 TAI-UTC= 21.0 S + (MJD - 41317.) X 0.0 S\n\
1131983 JUL 1 =JD 2445516.5 TAI-UTC= 22.0 S + (MJD - 41317.) X 0.0 S\n\
1141985 JUL 1 =JD 2446247.5 TAI-UTC= 23.0 S + (MJD - 41317.) X 0.0 S\n\
1151988 JAN 1 =JD 2447161.5 TAI-UTC= 24.0 S + (MJD - 41317.) X 0.0 S\n\
1161990 JAN 1 =JD 2447892.5 TAI-UTC= 25.0 S + (MJD - 41317.) X 0.0 S\n\
1171991 JAN 1 =JD 2448257.5 TAI-UTC= 26.0 S + (MJD - 41317.) X 0.0 S\n\
1181992 JUL 1 =JD 2448804.5 TAI-UTC= 27.0 S + (MJD - 41317.) X 0.0 S\n\
1191993 JUL 1 =JD 2449169.5 TAI-UTC= 28.0 S + (MJD - 41317.) X 0.0 S\n\
1201994 JUL 1 =JD 2449534.5 TAI-UTC= 29.0 S + (MJD - 41317.) X 0.0 S\n\
1211996 JAN 1 =JD 2450083.5 TAI-UTC= 30.0 S + (MJD - 41317.) X 0.0 S\n\
1221997 JUL 1 =JD 2450630.5 TAI-UTC= 31.0 S + (MJD - 41317.) X 0.0 S\n\
1231999 JAN 1 =JD 2451179.5 TAI-UTC= 32.0 S + (MJD - 41317.) X 0.0 S\n\
1242006 JAN 1 =JD 2453736.5 TAI-UTC= 33.0 S + (MJD - 41317.) X 0.0 S\n\
1252009 JAN 1 =JD 2454832.5 TAI-UTC= 34.0 S + (MJD - 41317.) X 0.0 S\n\
1262012 JUL 1 =JD 2456109.5 TAI-UTC= 35.0 S + (MJD - 41317.) X 0.0 S\n\
1272015 JUL 1 =JD 2457204.5 TAI-UTC= 36.0 S + (MJD - 41317.) X 0.0 S\n\
1282017 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.
133namespace {
134
136struct Leap {
137 long long whenUtc;
138 long long whenTai;
139 double offset;
140 double mjdRef;
141 double drift;
142};
143
144class LeapTable : public std::vector<Leap> {
145public:
146 LeapTable(void);
147};
148
149LeapTable leapSecTable;
150
151LeapTable::LeapTable(void) { dafBase::DateTime::initializeLeapSeconds(leapString); }
152
159template <typename NsType>
160NsType 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
183template <typename NsType>
184NsType 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
210long long nsecAnyToTai(long long nsecs, dafBase::DateTime::Timescale scale) {
211 switch (scale) {
212 case dafBase::DateTime::TAI:
213 return nsecs;
214 case dafBase::DateTime::TT:
215 return nsecs - TT_MINUS_TAI_NSECS;
216 case dafBase::DateTime::UTC:
217 return utcToTai(nsecs);
218 }
220 os << "Unsupported scale " << scale;
222}
223
231long long nsecTaiToAny(long long nsecs, dafBase::DateTime::Timescale scale) {
232 switch (scale) {
233 case dafBase::DateTime::TAI:
234 return nsecs;
235 case dafBase::DateTime::TT:
236 return nsecs + TT_MINUS_TAI_NSECS;
237 case dafBase::DateTime::UTC:
238 return taiToUtc(nsecs);
239 }
241 os << "Unsupported scale " << scale;
243}
244
245#ifdef CAL_TO_JD
257double 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
280namespace lsst {
281namespace daf {
282namespace base {
283
284void 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
296void DateTime::setNsecsFromJd(double jd, Timescale scale) { setNsecsFromMjd(jd - MJD_TO_JD, scale); }
297
303void DateTime::setNsecsFromEpoch(double epoch, Timescale scale) {
304 setNsecsFromMjd(365.25 * (epoch - 2000.0) + JD2000 - MJD_TO_JD, scale);
305}
306
307DateTime::DateTime() : _nsecs(DateTime::invalid_nsecs) {}
308
309DateTime::DateTime(long long nsecs, Timescale scale) : _nsecs(nsecAnyToTai(nsecs, scale)) {}
310
311DateTime::DateTime(double date, DateSystem system, Timescale scale) {
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
328DateTime::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
430double 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
448long 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
456double DateTime::_getMjd(Timescale scale) const {
457 _assertValid();
458 double nsecs = nsecTaiToAny(_nsecs, scale);
459 return nsecs / NSEC_PER_DAY + EPOCH_IN_MJD;
460}
461
462double DateTime::_getJd(Timescale scale) const { return _getMjd(scale) + MJD_TO_JD; }
463
464double DateTime::_getEpoch(Timescale scale) const { return 2000.0 + (_getJd(scale) - JD2000) / 365.25; }
465
466struct 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
482struct 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
491struct 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
514bool DateTime::operator==(DateTime const& rhs) const { return _nsecs == rhs._nsecs; }
515
516std::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;
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
static constexpr 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
T size(T... args)
T stod(T... args)
T str(T... args)