PSTime/src/Time.cpp

Go to the documentation of this file.
00001 
00002 //--------------------------------------------------------------------------
00003 // File and Version Information:
00004 //      $Id: Time.cpp 5859 2013-03-22 22:35:24Z salnikov@SLAC.STANFORD.EDU $
00005 //
00006 // Description:
00007 //      Class PSTime...
00008 //
00009 // Author List:
00010 //      Mikhail S. Dubrovin
00011 //
00012 //------------------------------------------------------------------------
00013 
00014 //-----------------------
00015 // This Class's Header --
00016 //-----------------------
00017 #include "PSTime/Time.h"
00018 
00019 //-----------------
00020 // C/C++ Headers --
00021 //-----------------
00022 #include <iostream>
00023 #include <string.h>
00024 
00025 //-------------------------------
00026 // Collaborating Class Headers --
00027 //-------------------------------
00028 #include "PSTime/Exceptions.h"
00029 #include "PSTime/TimeFormat.h"
00030 #include "PSTime/TimeUtils.h"
00031 
00032 //-----------------------------------------------------------------------
00033 // Local Macros, Typedefs, Structures, Unions and Forward Declarations --
00034 //-----------------------------------------------------------------------
00035 
00036 namespace {
00037 
00038   // number of nanoseconds in a second
00039   const uint32_t nsecInASec = 1000000000U;
00040   
00041 }
00042 
00043 //              ----------------------------------------
00044 //              -- Public Function Member Definitions --
00045 //              ----------------------------------------
00046 
00047 namespace PSTime {
00048 
00049 //----------------
00050 // Constructors --
00051 //----------------
00052 
00053 Time::Time () 
00054   : m_utcSec(0)
00055   , m_utcNsec(0)
00056 {
00057 }
00058 
00059 Time::Time (time_t utcSec, uint32_t utcNsec)
00060   : m_utcSec(utcSec)
00061   , m_utcNsec(utcNsec)
00062 {
00063 }
00064 
00065 Time::Time ( int  year,
00066              int  month,
00067              int  day,
00068              int  hour,
00069              int  min,
00070              int  sec,
00071              uint32_t  nsec,
00072              Zone zone)
00073   : m_utcSec(0)
00074   , m_utcNsec(nsec)
00075 {
00076   struct tm stm;
00077   stm.tm_year  = year - 1900; // Human: 2010,   tm year from: 1900
00078   stm.tm_mon   = month - 1;   // Human: [1,12], tm and POSIX: [0,11]
00079   stm.tm_mday  = day; 
00080   stm.tm_hour  = hour;
00081   stm.tm_min   = min;
00082   stm.tm_sec   = sec;
00083   stm.tm_isdst = -1;          // Let mktime figure out whether DST is in force
00084 
00085   if (zone == UTC) {
00086     m_utcSec  = TimeUtils::timegm( &stm );
00087   } else {
00088     m_utcSec  = mktime( &stm );
00089   }
00090 }
00091 
00092 Time::Time (struct timespec& ts)
00093 {
00094   m_utcSec  = ts.tv_sec;
00095   m_utcNsec = ts.tv_nsec;
00096 }
00097 
00098 Time::Time (struct tm& stm, Zone zone) 
00099   : m_utcSec(0)
00100   , m_utcNsec(0)
00101 {
00102   if (zone == UTC) {
00103     m_utcSec  = TimeUtils::timegm( &stm );
00104   } else {
00105     m_utcSec  = mktime( &stm );
00106   }
00107 }
00108 
00109 // tstamp can be presented in formats understood by in parse(...) method
00110 Time::Time (const std::string& tstamp)
00111   : m_utcSec(0)
00112   , m_utcNsec(0)
00113 {
00114   Time t = TimeFormat::parseTime(tstamp);
00115   m_utcSec  = t.m_utcSec; // or t.getUTCSec();
00116   m_utcNsec = t.m_utcNsec; // or t.getUTCNsec();
00117 }
00118 
00119 //--------------
00120 //  -- Operators
00121 //--------------
00122 
00123 // Arithmetic operators with Duration
00124 
00125 // d = |t2 - t1|
00126 Duration 
00127 Time::operator-( const Time& t1 ) const
00128 {
00129     // This code forms |t2-t1| without having to use signed intergers.
00130 
00131     time_t t2Sec;
00132     time_t t2Nsec;
00133     time_t t1Sec;
00134     time_t t1Nsec;
00135 
00136     if ( *this > t1 )
00137         {
00138             t2Sec  = m_utcSec;
00139             t2Nsec = m_utcNsec;
00140             t1Sec  = t1.m_utcSec;
00141             t1Nsec = t1.m_utcNsec;
00142         }
00143     else
00144         {
00145             t2Sec  = t1.m_utcSec;
00146             t2Nsec = t1.m_utcNsec;
00147             t1Sec  = m_utcSec;
00148             t1Nsec = m_utcNsec;
00149         }
00150 
00151     if ( t2Nsec < t1Nsec )
00152         {
00153             // borrow a second from t2Sec
00154             t2Nsec += ::nsecInASec;
00155             t2Sec--;
00156         }
00157 
00158     time_t sec  = t2Sec  - t1Sec;
00159     time_t nsec = t2Nsec - t1Nsec;
00160 
00161     Duration diff( sec, nsec );
00162 
00163     return diff;
00164 }
00165 
00166 
00167 
00168 // t -= d
00169 Time& 
00170 Time::operator-=( const Duration& d )
00171 {
00172   // if t1 - d < 0 then return t = 0
00173   if ( ( m_utcSec  < d.getSec() ) ||
00174        ( m_utcSec == d.getSec()   && m_utcNsec < d.getNsec() ) ) {
00175     m_utcSec  = 0;
00176     m_utcNsec = 0;
00177   }
00178   else {
00179     time_t tempSec  = m_utcSec;
00180     time_t tempNsec = m_utcNsec;
00181     
00182     if ( tempNsec < d.getNsec() ) {
00183       // if t1.m_utcNsec < d._nsec borrow a second from t1.m_utcSec
00184       tempNsec += ::nsecInASec;
00185       tempSec--;
00186     }
00187     
00188     m_utcSec  = tempSec  - d.getSec();
00189     m_utcNsec = tempNsec - d.getNsec();
00190   }
00191   
00192   return *this;
00193 }
00194 
00195 // t += d
00196 Time& 
00197 Time::operator+=( const Duration& d )
00198 {
00199   time_t totalSec  = m_utcSec  + d.getSec();
00200   time_t totalNsec = m_utcNsec + d.getNsec();
00201   
00202   if ( totalNsec >= ::nsecInASec ) {
00203     // carry nanoseconds over into seconds
00204     time_t extraSec   = totalNsec / ::nsecInASec;
00205     time_t remainNsec = totalNsec % ::nsecInASec;
00206     totalSec         += extraSec;
00207     totalNsec         = remainNsec;
00208   }
00209   
00210   m_utcSec  = totalSec;
00211   m_utcNsec = totalNsec;
00212 
00213   return *this;
00214 }
00215 
00216 
00217 //--------------------
00218 //  -- Public methods
00219 //--------------------
00220 
00221 struct timespec
00222 Time::getTimeSpec() const
00223 {
00224   struct timespec ts;
00225   ts.tv_sec  = m_utcSec;
00226   ts.tv_nsec = m_utcNsec;
00227   return ts;
00228 }
00229 
00230 struct tm
00231 Time::gettm( Zone zone ) const
00232 {
00233   struct tm stm;
00234   memset( &stm, 0, sizeof(stm)) ;
00235 
00236   if (zone == UTC) {
00237     gmtime_r(&m_utcSec, &stm);
00238   } else {
00239     localtime_r(&m_utcSec, &stm);    
00240   }
00241   
00242   return stm;
00243 }
00244 
00245 // Time stamp in fromat YYYY-MM-DD HH:MM:SS.NNNNNNNNN+HH:MM
00246 std::string 
00247 Time::asString( Zone zone, int nsecPrecision ) const
00248 {
00249   std::string fmt;
00250   if (nsecPrecision < 1) {
00251     fmt = "%F %T%z";
00252   } else {
00253     if (nsecPrecision > 9) nsecPrecision = 9;
00254     fmt = "%F %T%.9f%z";
00255     fmt[7] = char('0'+nsecPrecision);
00256   }
00257   return TimeFormat::format(*this, fmt, zone);
00258 }
00259 
00260 
00261 // Time stamp in fromat HHMMSSTHHMMSS+HHMM
00262 std::string 
00263 Time::asStringCompact( Zone zone, int nsecPrecision  ) const
00264 {
00265   std::string fmt;
00266   if (nsecPrecision < 1) {
00267     fmt = "%Y%m%dT%H%M%S%z";
00268   } else {
00269     if (nsecPrecision > 9) nsecPrecision = 9;
00270     fmt = "%Y%m%dT%H%M%S%.9f%z";
00271     fmt[15] = char('0'+nsecPrecision);
00272   }
00273   return TimeFormat::format(*this, fmt, zone);
00274 }
00275 
00276 
00277 // Time stamp in free fromat
00278 std::string 
00279 Time::asStringFormat( const std::string& fmt, Zone zone ) const
00280 {
00281   return TimeFormat::format(*this, fmt, zone);
00282 }
00283 
00284 /**
00285  *  Returns current time.
00286  */
00287 Time 
00288 Time::now() 
00289 {
00290   struct timespec ts;
00291   int status = clock_gettime( CLOCK_REALTIME, &ts );
00292 
00293   if( status == 0 ) {
00294     return Time(ts.tv_sec, ts.tv_nsec);
00295   } else {
00296     throw ErrnoException( ERR_LOC, "clock_gettime failed");
00297   }
00298   
00299 }
00300 
00301 std::ostream& 
00302 operator <<( std::ostream& os, const Time& t ) 
00303 {
00304   TimeFormat::format(os, t, "%F %T%f%z", Time::Local);
00305   return os;
00306 }
00307 
00308 //--------------
00309 } // namespace PSTime
00310 

Generated on 19 Dec 2016 for PSANAclasses by  doxygen 1.4.7