#ifndef TIM_C #define TIM_C /** * @since 2006-08-28 * @author Richard J. Mathar */ #include #include #include #include #include #include #include #include #include #include #include #include "slalib.h" #include "prconst.h" using namespace std ; using namespace CCfits ; #include "Tim.h" using namespace boost ; using namespace posix_time ; /** * similar to from_iso_string() in time_parsers.hpp */ ptime eso_string2ptime(const std::string & s) { using namespace date_time ; using namespace posix_time ; //split date/time on a unique delimiter char such as ' ' or 'T' std::string date_string, tod_string; split(s, 'T', date_string, tod_string); //call parse_date with first string gregorian::date d = parse_date(date_string); //call parse_time_duration with remaining string posix_time::time_duration td = duration_from_string(tod_string); /* debugging *cerr << __LINE__ << " " << d << " " << td << endl ; */ //construct a time return ptime(d, td); } ptime FITS2ptime(FITS & f) { PHDU & p = f.pHDU() ; string key("DATE-OBS") ; /** * Read DATE-OBS from the primary FITS header. */ string datobs ; p.readKey(key, datobs) ; /* debugging * cerr << datobs << endl ; */ /** * Deconstruct the YYYY-MM-DDTHH:MM:SS.sss with an accuracy of 1 second. */ return eso_string2ptime(datobs) ; } /** * Default ctor * This is mainly needed to construct vectors of the StarObserv class below. */ Tim::Tim() : ptime() { /* this would be the MJD at 1970-01-01 */ modJD = 40587.0 ; } /** * ctor * @param p the ptime representation of the point in time */ Tim::Tim(ptime &p) : ptime(p) { modJD = mjd(false) ; } /** ctor reading the MJD-OBS string from the primary header * ctor * @param f the FITS object containing a PHDU */ Tim::Tim(FITS &f) : ptime( FITS2ptime(f) ) { modJD = mjd(false) ; /* debuging * cerr << __FILE__ << " " << __LINE__ << " " << *this << endl ; * cerr << __FILE__ << " " << __LINE__ << " " << setprecision(15) << modJD << endl ; */ } /** Ctor with input of the format YYYY-MM-DDTHH:MM:SS.sss * Similar to from_iso_string() in time_parsers.hpp * @paramp[in] s the time specification as a string in the ESO format */ Tim::Tim(const std::string & s) : ptime( eso_string2ptime(s) ) { modJD = mjd(false) ; } /** Ctor with a MJD provided. * The action to convert the MJD into a civilian time is approximately the * inverse of the one inside Tim::mjd() . * @param[in] mjdat the modified Julian date * @since 2006-08-28 * @author Richard J. Mathar */ Tim::Tim(const double mjdat) { using namespace boost ; using namespace posix_time ; /* * Use the slalib to convert modified Julian day into a standard * 24 hr day. */ double fracday ; int stat=0 ; int year, month, day ; slaDjcl(mjdat,&year,&month,&day,&fracday,&stat) ; if ( stat ) { cerr << __FILE__ << " " << __LINE__ << " cannot parse " << mjdat << endl ; exit(EXIT_FAILURE) ; } int ihmsf[4] ; char sign ; slaDd2tf(6,fracday,&sign,ihmsf) ; const time_duration td = hours(ihmsf[0])+minutes(ihmsf[1])+seconds(ihmsf[2])+microseconds(ihmsf[3]) ; ptime then( gregorian::date(year,(unsigned short)month,day) , td) ; // *this = ptime::operator=((ptime)t) ; *this = then ; modJD=mjdat ; } #if 0 /** assignment operator * superfluous as member-by-member copy suffices. */ Tim::Tim & operator= (const Tim & oth ) { if( this != &oth) { //(ptime)(*this)= oth ; *this = ptime::operator=((ptime)oth) ; modJD = oth.modJD ; } return *this; } #endif /** * Convert the time into the Greenwich Mean sidereal time * @return GMST in units of radians */ double Tim::gmst() const { return slaGmst(modJD) ; } void Tim::sync(const ptime t) { #if 0 const time_duration td = t- (*this) ; (ptime)(*this) += td ; #else *this = ptime::operator=((ptime)t) ; #endif modJD = mjd(false) ; } /* construct MJD or JD. * setting jd=true means not the modified but the actual JD are computed * CCS/tims/src/timsUTCToJD.c */ double Tim::mjd(bool jd) const { using namespace posix_time ; #if 1 const time_duration td = time_of_day() ; const gregorian::date d = date() ; /* * Use the slalib to convert the day into a modified Julian day. */ double result ; int stat=0 ; slaCaldj(d.year(),d.month(),d.day(),&result,&stat) ; if ( stat ) { cerr << __FILE__ << " " << __LINE__ << " cannot parse " << d << endl ; exit(EXIT_FAILURE) ; } result += (td.total_seconds() + (double)(td.fractional_seconds())/time_duration::ticks_per_second() ) / SECPERDAY ; if (jd ) result += 2400000.5 ; return result ; #else // first convert into UNIX seconds, ignoring/truncating the fractional seconds struct tm tmTime = to_tm(*this) ; tmTime.tm_isdst = 0 ; // no DST setenv("TZ","UTC",1) ; // enforce GMT // cout << mktime(&tmTime) << endl ; // cout << asctime(&tmTime) << endl ; /* Adjust for fractional seconds: * Compute the time since midnight in units of microseconds; chop off the seconds * that have already been taken into account when constructing the time_t value. * Convert the microseconds into values between 0. and 1. This has the potential of * overflow, since the microseconds would often not fit into the 32 bit long format of the * local compiler. */ const time_duration td = time_of_day() ; double result = mktime(&tmTime) + 1.e-6*(td.total_microseconds() % 1000000) ; /* Add 2440587.5 which is JD for 1970-01-01 00:00:00.000000, * and subtract 2400000.5 if the MJD is requested */ if (jd ) return result/SECPERDAY+2440587.5 ; else return result/SECPERDAY+2440587.5-2400000.5 ; #endif } Tim operator+ (const Tim &left, const posix_time::time_duration & td) { ptime resul = (ptime)left + td; /* It might be much faster to update modJd as below instead of using the re-computation * inside the Tim ctor * modJD += (td.total_seconds() + (double)(td.fractional_seconds())/time_duration::ticks_per_second() ) / SECPERDAY ; */ return Tim(resul) ; } /** */ Tim & Tim::operator+= (const posix_time::time_duration & td) { return *this = *this + td ; } // output a string YYYY-MM-DDTHH:MM:SS.sss measured in UTC (no blanks or cr/lf or anything added) ostream & operator<<(ostream &os, const Tim & somespec) { /* debugging of the fractional seconds conversion * const time_duration td = somespec.time_of_day() ; *os << to_iso_extended_string(somespec) << "/" << td.fractional_seconds() ; */ os << to_iso_extended_string(somespec) ; return os ; } // __oOo__ #endif // TIM_C