00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "PSTime/Duration.h"
00017
00018
00019
00020
00021 #include <iostream>
00022 #include <iomanip>
00023 #include <math.h>
00024 #include <stdint.h>
00025 #include <stdio.h>
00026 #include <stdlib.h>
00027
00028 using namespace std;
00029
00030 namespace {
00031
00032
00033 const uint32_t nsecInASec = 1000000000U;
00034
00035 }
00036
00037 namespace PSTime {
00038
00039
00040
00041
00042 Duration::Duration () : m_sec( 0 ), m_nsec( 0 )
00043 {
00044 }
00045
00046
00047 Duration::Duration( const Duration & d ) : m_sec( d.m_sec ), m_nsec( d.m_nsec )
00048 {
00049 }
00050
00051
00052 Duration::Duration( time_t sec, time_t nsec )
00053 {
00054 if ( nsec >= ::nsecInASec )
00055 {
00056
00057 time_t extraSec = nsec / ::nsecInASec;
00058 time_t remainNsec = nsec % ::nsecInASec;
00059 sec += extraSec;
00060 nsec = remainNsec;
00061 }
00062
00063 m_sec = sec;
00064 m_nsec = nsec;
00065 }
00066
00067
00068 Duration::Duration( time_t Years,
00069 time_t Days,
00070 time_t Hours,
00071 time_t Mins,
00072 time_t Secs,
00073 time_t Nsecs )
00074 {
00075 time_t SecsInYDHMS = Secs + 60*(Mins + 60*(Hours + 24*(Days + 364*Years)));
00076 Duration total( SecsInYDHMS, Nsecs );
00077 m_sec = total.m_sec;
00078 m_nsec = total.m_nsec;
00079 }
00080
00081
00082
00083
00084
00085
00086
00087 Duration Duration::operator - ( const Duration & d1 ) const
00088 {
00089
00090
00091 time_t d2Sec;
00092 time_t d2Nsec;
00093 time_t d1Sec;
00094 time_t d1Nsec;
00095
00096 if ( *this > d1 )
00097 {
00098 d2Sec = m_sec;
00099 d2Nsec = m_nsec;
00100 d1Sec = d1.m_sec;
00101 d1Nsec = d1.m_nsec;
00102 }
00103 else
00104 {
00105 d2Sec = d1.m_sec;
00106 d2Nsec = d1.m_nsec;
00107 d1Sec = m_sec;
00108 d1Nsec = m_nsec;
00109 }
00110
00111 if ( d2Nsec < d1Nsec )
00112 {
00113
00114 d2Nsec += ::nsecInASec;
00115 d2Sec--;
00116 }
00117
00118 time_t sec = d2Sec - d1Sec;
00119 time_t nsec = d2Nsec - d1Nsec;
00120
00121 Duration diff( sec, nsec );
00122 return diff;
00123 }
00124
00125
00126
00127 Duration Duration::operator + ( const Duration & d1 ) const
00128 {
00129 time_t totalSec = m_sec + d1.m_sec;
00130 time_t totalNsec = m_nsec + d1.m_nsec;
00131
00132 if ( totalNsec >= ::nsecInASec )
00133 {
00134
00135 time_t extraSec = totalNsec / ::nsecInASec;
00136 time_t remainNsec = totalNsec % ::nsecInASec;
00137 totalSec += extraSec;
00138 totalNsec = remainNsec;
00139 }
00140
00141 Duration sum( totalSec, totalNsec );
00142
00143 return sum;
00144 }
00145
00146
00147
00148 Duration & Duration::operator = ( const Duration & d1 )
00149 {
00150 m_sec = d1.m_sec;
00151 m_nsec = d1.m_nsec;
00152 return *this;
00153 }
00154
00155
00156
00157 Duration & Duration::operator += ( const Duration & d1 )
00158 {
00159 time_t totalSec = m_sec + d1.m_sec;
00160 time_t totalNsec = m_nsec + d1.m_nsec;
00161
00162 if ( totalNsec >= ::nsecInASec )
00163 {
00164
00165 time_t extraSec = totalNsec / ::nsecInASec;
00166 time_t remainNsec = totalNsec % ::nsecInASec;
00167 totalSec += extraSec;
00168 totalNsec = remainNsec;
00169 }
00170
00171 m_sec = totalSec;
00172 m_nsec = totalNsec;
00173 return *this;
00174 }
00175
00176
00177
00178
00179
00180 void Duration::Print() const
00181 {
00182 printf ( "Duration:: m_sec = %ld m_nsec = %ld \n", m_sec, m_nsec);
00183
00184 time_t Years(0);
00185 time_t DaysAfterY(0);
00186 time_t HoursAfterD(0);
00187 time_t MinsAfterH(0);
00188 time_t SecsAfterM(0);
00189
00190 splitDurationSecsForYDHMS( Years,
00191 DaysAfterY,
00192 HoursAfterD,
00193 MinsAfterH,
00194 SecsAfterM );
00195
00196 printf ( "Duration: P%ldY%ldDT%dH%dM%dS ",
00197 Years,
00198 DaysAfterY,
00199 (int)HoursAfterD,
00200 (int)MinsAfterH,
00201 (int)SecsAfterM );
00202 printf ( " or P%ldY %ldD T%dH %dM %dS ",
00203 Years,
00204 DaysAfterY,
00205 (int)HoursAfterD,
00206 (int)MinsAfterH,
00207 (int)SecsAfterM );
00208
00209 printf ( " or %s \n", strDurationBasic().data() );
00210 }
00211
00212
00213 string Duration::strDurationBasic() const
00214 {
00215 time_t Years(0);
00216 time_t DaysAfterY(0);
00217 time_t HoursAfterD(0);
00218 time_t MinsAfterH(0);
00219 time_t SecsAfterM(0);
00220
00221 splitDurationSecsForYDHMS( Years,
00222 DaysAfterY,
00223 HoursAfterD,
00224 MinsAfterH,
00225 SecsAfterM );
00226 time_t NsecAfterS = m_nsec;
00227
00228 string strD = "P";
00229
00230 if ( Years != 0 ) { char charY[8]; snprintf( charY, sizeof charY, "%ldY",Years ); strD += charY; }
00231 if ( DaysAfterY != 0 ) { char charD[8]; snprintf( charD, sizeof charD, "%ldD",DaysAfterY ); strD += charD; }
00232
00233 strD += "T";
00234
00235 if ( HoursAfterD!= 0 ) { char charH[8]; snprintf( charH, sizeof charH,"%ldH",HoursAfterD ); strD += charH; }
00236 if ( MinsAfterH != 0 ) { char charM[8]; snprintf( charM, sizeof charM,"%ldM",MinsAfterH ); strD += charM; }
00237 if ( SecsAfterM != 0 ) { char charS[8]; snprintf( charS, sizeof charS,"%ldS",SecsAfterM ); strD += charS; }
00238 if ( NsecAfterS != 0 ) { char charN[16]; snprintf( charN, sizeof charN,"%ldN",NsecAfterS ); strD += charN; }
00239
00240 return strD;
00241 }
00242
00243
00244
00245
00246
00247
00248
00249
00250 int Duration::parseStringToDuration( const std::string& str_dur, Duration& d )
00251 {
00252 d.m_sec = 0;
00253 d.m_nsec = 0;
00254
00255
00256 size_t len_str_dur = str_dur.size();
00257 if( len_str_dur < 3 ) {return DURATION_STRING_TOO_SHORT;}
00258 if( len_str_dur > 30) {return DURATION_STRING_TOO_LONG;}
00259
00260
00261 size_t posP = str_dur.find('P');
00262 size_t posY = str_dur.find('Y');
00263 size_t posD = str_dur.find('D');
00264 size_t posT = str_dur.find('T');
00265 size_t posH = str_dur.find('H');
00266 size_t posF = str_dur.find('.');
00267 size_t posS = str_dur.find('S');
00268 size_t posM = str_dur.find_first_of('M');
00269 size_t posMin = str_dur.find_last_of('M');
00270
00271 if ( posP == string::npos ) { return DURATION_STRING_WRONG_FORMAT_MISSING_P; }
00272
00273 size_t posN1 = posP + 1;
00274 size_t posNN;
00275
00276
00277 if ( posY != string::npos ) {
00278 posNN = posY - 1;
00279 size_t lenY = posNN - posN1 + 1;
00280 if( lenY > 7 ) {return DURATION_TOO_LONG_FIELD_FOR_YEARS;}
00281 char charY[8];
00282 size_t lenY_copy=str_dur.copy(charY,lenY,posN1); charY[lenY_copy] = '\0';
00283 d.m_sec += atoi(charY)*3600*24*364;
00284 posN1 = posY + 1;
00285 }
00286
00287
00288 if ( posM != string::npos ) {
00289 posNN = posM - 1;
00290 size_t lenM = posNN - posN1 + 1;
00291 if( lenM > 7 ) {return DURATION_TOO_LONG_FIELD_FOR_MONTHS;}
00292 char charM[8];
00293 size_t lenM_copy=str_dur.copy(charM,lenM,posN1); charM[lenM_copy] = '\0';
00294 d.m_sec += atoi(charM)*3600*24*30;
00295 posN1 = posM + 1;
00296 }
00297
00298
00299 if ( posD != string::npos ) {
00300 posNN = posD - 1;
00301 size_t lenD = posNN - posN1 + 1;
00302 if( lenD > 7 ) {return DURATION_TOO_LONG_FIELD_FOR_DAYS;}
00303 char charD[8];
00304 size_t lenD_copy=str_dur.copy(charD,lenD,posN1); charD[lenD_copy] = '\0';
00305 d.m_sec += atoi(charD)*3600*24;
00306 posN1 = posD + 2;
00307 }
00308
00309
00310 if ( posT != string::npos ) {
00311 posN1 = posT + 1;
00312 }
00313 else
00314 {
00315 return PARSE_IS_OK;
00316 }
00317
00318
00319 if ( posH != string::npos ) {
00320 posNN = posH - 1;
00321 size_t lenH = posNN - posN1 + 1;
00322 if( lenH > 7 ) {return DURATION_TOO_LONG_FIELD_FOR_HOURS;}
00323 char charH[8];
00324 size_t lenH_copy=str_dur.copy(charH,lenH,posN1); charH[lenH_copy] = '\0';
00325 d.m_sec += atoi(charH)*3600;
00326 posN1 = posH + 1;
00327 }
00328
00329
00330 if ( posMin != string::npos ) {
00331 posNN = posMin - 1;
00332 size_t lenM = posNN - posN1 + 1;
00333 if( lenM > 7 ) {return DURATION_TOO_LONG_FIELD_FOR_MINUTES;}
00334 char charM[8];
00335 size_t lenM_copy=str_dur.copy(charM,lenM,posN1); charM[lenM_copy] = '\0';
00336 d.m_sec += atoi(charM)*60;
00337 posN1 = posMin + 1;
00338 }
00339
00340
00341
00342 if ( posF != string::npos && posS != string::npos) {
00343 posNN = posF - 1;
00344 size_t lenS = posNN - posN1 + 1;
00345 if( lenS > 15 ) {return DURATION_TOO_LONG_FIELD_FOR_SECONDS;}
00346 char charS[16];
00347 size_t lenS_copy=str_dur.copy(charS,lenS,posN1); charS[lenS_copy] = '\0';
00348 d.m_sec += atoi(charS);
00349 posN1 = posF + 1;
00350
00351
00352 posNN = posS - 1;
00353 size_t lenF = posNN - posN1 + 1;
00354 if( lenF > 9 ) {return DURATION_TOO_LONG_FIELD_FOR_SECOND_FRACTION;}
00355 char charF[16];
00356 size_t lenF_copy=str_dur.copy(charF,lenF,posN1); charF[lenF_copy] = '\0';
00357 double frac_of_sec = (double)atoi(charF);
00358 d.m_nsec = (size_t)(frac_of_sec * pow(10,9-lenF_copy));
00359 return PARSE_IS_OK;
00360 }
00361
00362
00363 if ( posS != string::npos) {
00364 posNN = posS - 1;
00365 size_t lenS = posNN - posN1 + 1;
00366 if( lenS > 7 ) {return DURATION_TOO_LONG_FIELD_FOR_SECONDS;}
00367 char charS[16];
00368 size_t lenS_copy=str_dur.copy(charS,lenS,posN1); charS[lenS_copy] = '\0';
00369 d.m_sec += atoi(charS);
00370 posN1 = posF + 1;
00371 }
00372 return PARSE_IS_OK;
00373 }
00374
00375
00376
00377
00378
00379 void Duration::splitDurationSecsForYDHMS(time_t &Years,
00380 time_t &DaysAfterY,
00381 time_t &HoursAfterD,
00382 time_t &MinsAfterH,
00383 time_t &SecsAfterM) const
00384 {
00385 Years = m_sec / (364*24*3600);
00386 time_t SecsAfterY = m_sec % (364*24*3600);
00387 DaysAfterY = SecsAfterY / (24*3600);
00388 time_t SecsAfterD = SecsAfterY % (24*3600);
00389 HoursAfterD = SecsAfterD / 3600;
00390 time_t SecsAfterH = SecsAfterD % 3600;
00391 MinsAfterH = SecsAfterH / 60;
00392 SecsAfterM = SecsAfterH % 60;
00393 }
00394
00395
00396
00397
00398
00399
00400
00401 ostream & operator << ( ostream & os, const Duration & d )
00402 {
00403 if ( d.m_nsec == 0 )
00404 {
00405 os << d.m_sec << " sec";
00406 return os;
00407 }
00408 else
00409 {
00410 cout.fill( '0' );
00411 os << d.m_sec << "." << setw(9) << d.m_nsec << " sec";
00412 cout.fill( ' ' );
00413 return os;
00414 }
00415 }
00416
00417 }