00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "PSTime/Time.h"
00018
00019
00020
00021
00022 #include <iostream>
00023 #include <string.h>
00024
00025
00026
00027
00028 #include "PSTime/Exceptions.h"
00029 #include "PSTime/TimeFormat.h"
00030 #include "PSTime/TimeUtils.h"
00031
00032
00033
00034
00035
00036 namespace {
00037
00038
00039 const uint32_t nsecInASec = 1000000000U;
00040
00041 }
00042
00043
00044
00045
00046
00047 namespace PSTime {
00048
00049
00050
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;
00078 stm.tm_mon = month - 1;
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;
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
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;
00116 m_utcNsec = t.m_utcNsec;
00117 }
00118
00119
00120
00121
00122
00123
00124
00125
00126 Duration
00127 Time::operator-( const Time& t1 ) const
00128 {
00129
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
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
00169 Time&
00170 Time::operator-=( const Duration& d )
00171 {
00172
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
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
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
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
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
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
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
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
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 }
00310