LSST Applications g06d8191974+de063e15a7,g180d380827+d0b6459378,g2079a07aa2+86d27d4dc4,g2305ad1205+f1ae3263cc,g29320951ab+5752d78b6e,g2bbee38e9b+85cf0a37e7,g337abbeb29+85cf0a37e7,g33d1c0ed96+85cf0a37e7,g3a166c0a6a+85cf0a37e7,g3ddfee87b4+b5254b9343,g48712c4677+9ea88d309d,g487adcacf7+05f7dba17f,g50ff169b8f+96c6868917,g52b1c1532d+585e252eca,g591dd9f2cf+48904e3942,g64a986408d+de063e15a7,g858d7b2824+de063e15a7,g864b0138d7+33ab2bc355,g8a8a8dda67+585e252eca,g99cad8db69+4508353287,g9c22b2923f+53520f316c,g9ddcbc5298+9a081db1e4,ga1e77700b3+15fc3df1f7,gb0e22166c9+60f28cb32d,gba4ed39666+c2a2e4ac27,gbb8dafda3b+ccb7f83a87,gc120e1dc64+6caf640b9b,gc28159a63d+85cf0a37e7,gc3e9b769f7+548c5e05a3,gcf0d15dbbd+b5254b9343,gdaeeff99f8+f9a426f77a,ge6526c86ff+515b6c9330,ge79ae78c31+85cf0a37e7,gee10cc3b42+585e252eca,gff1a9f87cc+de063e15a7,w.2024.17
LSST Data Management Base Package
Loading...
Searching...
No Matches
Public Types | Public Member Functions | Static Public Member Functions | Static Public Attributes | Friends | List of all members
lsst::daf::base::DateTime Class Reference

Class for handling dates/times, including MJD, UTC, and TAI. More...

#include <DateTime.h>

Public Types

enum  DateSystem { JD = 0 , MJD , EPOCH }
 
enum  Timescale { TAI = 5 , UTC , TT }
 

Public Member Functions

 DateTime ()
 Default constructor: construct an invalid DateTime.
 
 DateTime (long long nsecs, Timescale scale=TAI)
 Construct a DateTime from nanoseconds since the unix epoch.
 
 DateTime (double date, DateSystem system=MJD, Timescale scale=TAI)
 Construct a DateTime from a double in the specified system and scale.
 
 DateTime (int year, int month, int day, int hr, int min, int sec, Timescale scale=TAI)
 Construct a DateTime from year, month, day, etc.
 
 DateTime (std::string const &iso8601, Timescale scale)
 Construct a DateTime from an ISO8601 string.
 
long long nsecs (Timescale scale=TAI) const
 Get date as nanoseconds since the unix epoch.
 
double get (DateSystem system=MJD, Timescale scale=TAI) const
 Get date as a double in a specified representation, such as MJD.
 
std::string toString (Timescale scale) const
 Get date as an ISO8601-formatted string.
 
struct tm gmtime (Timescale scale) const
 Get date as a tm struct, with truncated fractional seconds.
 
struct timespec timespec (Timescale scale) const
 Get date as a timespec struct, with time in seconds and nanoseconds.
 
struct timeval timeval (Timescale scale) const
 Get date as a timeval struct, with time in seconds and microseconds.
 
bool isValid () const
 Is this date valid?
 
bool operator== (DateTime const &rhs) const
 
std::size_t hash_value () const noexcept
 Return a hash of this object.
 

Static Public Member Functions

static DateTime now (void)
 Return current time as a DateTime.
 
static void initializeLeapSeconds (std::string const &leapString)
 Initialize the leap second table from USNO.
 

Static Public Attributes

static constexpr long long invalid_nsecs = std::numeric_limits<std::int64_t>::min()
 

Friends

class boost::serialization::access
 

Detailed Description

Class for handling dates/times, including MJD, UTC, and TAI.

Definition at line 64 of file DateTime.h.

Member Enumeration Documentation

◆ DateSystem

Enumerator
JD 
MJD 
EPOCH 

Definition at line 66 of file DateTime.h.

66{ JD = 0, MJD, EPOCH }; // EPOCH is Julian epoch year

◆ Timescale

Enumerator
TAI 
UTC 
TT 

Definition at line 68 of file DateTime.h.

68 {
69 TAI = 5,
70 UTC,
71 TT
72 }; // use values that do not overlap DateSystem

Constructor & Destructor Documentation

◆ DateTime() [1/5]

lsst::daf::base::DateTime::DateTime ( )
explicit

Default constructor: construct an invalid DateTime.

Definition at line 307 of file DateTime.cc.

307: _nsecs(DateTime::invalid_nsecs) {}
static constexpr long long invalid_nsecs
Definition DateTime.h:75

◆ DateTime() [2/5]

lsst::daf::base::DateTime::DateTime ( long long nsecs,
Timescale scale = TAI )
explicit

Construct a DateTime from nanoseconds since the unix epoch.

Parameters
[in]nsecsinteger nanoseconds since the unix epoch; if nsecs == DateTime.invalid_nsecs then the DateTime is invalid, regardless of scale
[in]scaletime scale of input (TAI, TT or UTC, default TAI).
Exceptions
lsst.pex.exceptions.DomainErrorif scale is UTC and the date is before 1961-01-01

Definition at line 309 of file DateTime.cc.

309: _nsecs(nsecAnyToTai(nsecs, scale)) {}
long long nsecs(Timescale scale=TAI) const
Get date as nanoseconds since the unix epoch.
Definition DateTime.cc:448

◆ DateTime() [3/5]

lsst::daf::base::DateTime::DateTime ( double date,
DateSystem system = MJD,
Timescale scale = TAI )
explicit

Construct a DateTime from a double in the specified system and scale.

Parameters
[in]datespecified date
[in]systemtime system of input (JD, MJD, or [Julian] EPOCH)
[in]scaletime scale of input (TAI, TT or UTC, default TAI).
Exceptions
lsst.pex.exceptions.DomainErrorif scale is UTC and the date is before 1961-01-01

Definition at line 311 of file DateTime.cc.

311 {
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}
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
Definition Exception.h:48
Reports invalid arguments.
Definition Runtime.h:66

◆ DateTime() [4/5]

lsst::daf::base::DateTime::DateTime ( int year,
int month,
int day,
int hr,
int min,
int sec,
Timescale scale = TAI )

Construct a DateTime from year, month, day, etc.

(tm struct fields)

Parameters
[in]yearyear; must be in the range [1902, 2261], inclusive.
[in]monthmonth number, where January = 1
[in]dayday of the month (1 to 31).
[in]hrhour (0 to 23)
[in]minminute (0 to 59)
[in]secinteger seconds (0 to 60)
[in]scaletime scale of input (TAI, TT or UTC, default TAI).
Exceptions
lsst.pex.exceptions.DomainErrorif year is < 1902 or > 2261, or if scale is UTC and the date is before 1961-01-01 (the start of the leap second table)

Definition at line 328 of file DateTime.cc.

328 {
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}
int min
Reports arguments outside the domain of an operation.
Definition Runtime.h:57

◆ DateTime() [5/5]

lsst::daf::base::DateTime::DateTime ( std::string const & iso8601,
Timescale scale )
explicit

Construct a DateTime from an ISO8601 string.

Accepts a restricted subset of ISO8601: yyyy-mm-ddThh:mm:ss.nnnnnnnnnZ where:

  • the final Z is required for UTC and prohibited for TAI or TT
  • the - and : separators are optional
  • the decimal point and fractional seconds are optional
  • the decimal point may be a comma
Parameters
[in]iso8601ISO8601 string representation of date and time
[in]scaletime scale of input (TAI, TT or UTC, default TAI).
Exceptions
lsst.pex.exceptions.DomainErrorif year is < 1902 or > 2261, or if scale is UTC and the date is before 1961-01-01 (the start of the leap second table)

Definition at line 386 of file DateTime.cc.

386 {
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}
T atoi(T... args)
T c_str(T... args)
T erase(T... args)
T regex_match(T... args)
T size(T... args)
T str(T... args)

Member Function Documentation

◆ get()

double lsst::daf::base::DateTime::get ( DateSystem system = MJD,
Timescale scale = TAI ) const

Get date as a double in a specified representation, such as MJD.

Returns
the date in the required system, for the requested scale
Parameters
[in]systemdesired time system (JD, MJD, or [Julian] EPOCH)
[in]scaledesired time scale (TAI, TT or UTC)
Exceptions
lsst.pex.exceptions.DomainErrorif scale is UTC and the UTC date is before 1961-01-01
lsst.pex.exceptions.RuntimeErrorif DateTime is invalid

Definition at line 430 of file DateTime.cc.

430 {
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}

◆ gmtime()

struct tm lsst::daf::base::DateTime::gmtime ( Timescale scale) const

Get date as a tm struct, with truncated fractional seconds.

Parameters
[in]scaledesired time scale (TAI, TT or UTC)
Returns
date as a tm struct
Exceptions
lsst.pex.exceptions.DomainErrorif scale is UTC and the UTC date is before 1961-01-01
lsst.pex.exceptions.RuntimeErrorif DateTime is invalid

Definition at line 466 of file DateTime.cc.

466 {
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}

◆ hash_value()

std::size_t lsst::daf::base::DateTime::hash_value ( ) const
noexcept

Return a hash of this object.

Definition at line 516 of file DateTime.cc.

516{ return std::hash<long long>()(_nsecs); }

◆ initializeLeapSeconds()

void lsst::daf::base::DateTime::initializeLeapSeconds ( std::string const & leapString)
static

Initialize the leap second table from USNO.

The data can be found here: http://maia.usno.navy.mil/ser7/tai-utc.dat and is saved in DateTime.cc as static constant leapString.

Parameters
leapStringleap second table from USNO as a single multiline string.

Definition at line 528 of file DateTime.cc.

528 {
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}
T begin(T... args)
T end(T... args)
T stod(T... args)

◆ isValid()

bool lsst::daf::base::DateTime::isValid ( ) const
inline

Is this date valid?

Definition at line 203 of file DateTime.h.

203{ return _nsecs != DateTime::invalid_nsecs; };

◆ now()

DateTime lsst::daf::base::DateTime::now ( void )
static

Return current time as a DateTime.

Assumes the system clock keeps UTC, as almost all computers do.

Definition at line 518 of file DateTime.cc.

518 {
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}
DateTime()
Default constructor: construct an invalid DateTime.
Definition DateTime.cc:307
struct timeval timeval(Timescale scale) const
Get date as a timeval struct, with time in seconds and microseconds.
Definition DateTime.cc:491
Reports errors that are due to events beyond the control of the program.
Definition Runtime.h:104

◆ nsecs()

long long lsst::daf::base::DateTime::nsecs ( Timescale scale = TAI) const

Get date as nanoseconds since the unix epoch.

Note
If the DateTime is invalid then the returned value is DateTime.invalid_nsecs, regardless of scale.
Parameters
[in]scaledesired time scale (TAI, TT or UTC)
Returns
the date as nanoseconds since the unix epoch in the specified time scale
Exceptions
lsst.pex.exceptions.DomainErrorif scale is UTC and the UTC date is before 1961-01-01

Definition at line 448 of file DateTime.cc.

448 {
449 if (!isValid()) {
450 // return the same invalid value for all time scales
452 }
453 return nsecTaiToAny(_nsecs, scale);
454}
bool isValid() const
Is this date valid?
Definition DateTime.h:203

◆ operator==()

bool lsst::daf::base::DateTime::operator== ( DateTime const & rhs) const

Definition at line 514 of file DateTime.cc.

514{ return _nsecs == rhs._nsecs; }

◆ timespec()

struct timespec lsst::daf::base::DateTime::timespec ( Timescale scale) const

Get date as a timespec struct, with time in seconds and nanoseconds.

Parameters
[in]scaleDesired time scale (TAI, TT or UTC)
Returns
date as a timespec struct
Exceptions
lsst.pex.exceptions.DomainErrorif scale is UTC and the UTC date is before 1961-01-01
lsst.pex.exceptions.RuntimeErrorif DateTime is invalid

Definition at line 482 of file DateTime.cc.

482 {
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}
struct timespec timespec(Timescale scale) const
Get date as a timespec struct, with time in seconds and nanoseconds.
Definition DateTime.cc:482

◆ timeval()

struct timeval lsst::daf::base::DateTime::timeval ( Timescale scale) const

Get date as a timeval struct, with time in seconds and microseconds.

Parameters
[in]scaledesired time scale (TAI, TT or UTC)
Returns
date as a timeval struct
Exceptions
lsst.pex.exceptions.DomainErrorif scale is UTC and the UTC date is before 1961-01-01
lsst.pex.exceptions.RuntimeErrorif DateTime is invalid

Definition at line 491 of file DateTime.cc.

491 {
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}

◆ toString()

std::string lsst::daf::base::DateTime::toString ( Timescale scale) const

Get date as an ISO8601-formatted string.

The returned format is: yyyy-mm-ddThh:mm:ss.sssssssssZ where the final Z is only present if scale is UTC

Parameters
[in]scaleDesired time scale (TAI, TT or UTC).
Exceptions
lsst.pex.exceptions.DomainErrorif scale is UTC and the UTC date is before 1961-01-01
lsst.pex.exceptions.RuntimeErrorif DateTime is invalid

Definition at line 500 of file DateTime.cc.

500 {
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}
struct tm gmtime(Timescale scale) const
Get date as a tm struct, with truncated fractional seconds.
Definition DateTime.cc:466
scale(algorithm, min, max=None, frame=None)
Definition ds9.py:108

Friends And Related Symbol Documentation

◆ boost::serialization::access

friend class boost::serialization::access
friend

Definition at line 291 of file DateTime.h.

Member Data Documentation

◆ invalid_nsecs

constexpr long long lsst::daf::base::DateTime::invalid_nsecs = std::numeric_limits<std::int64_t>::min()
staticconstexpr

Definition at line 75 of file DateTime.h.


The documentation for this class was generated from the following files: