Line data Source code
1 : /// $Id: TimeStamp.cpp,v 1.5 2007/09/20 18:06:48 pgrenz Exp $
2 : ///
3 : /// @author Paul Grenz
4 : ///
5 : ////////////////////////////////////////////////////////////////////////////////
6 :
7 : #include <sstream>
8 : #include <iomanip>
9 : #include <algorithm>
10 : #include <limits>
11 : #include <stdio.h>
12 : #include <iostream>
13 :
14 : #include "TimeStamp.hpp"
15 :
16 : using std::string;
17 : using std::ostream;
18 : using std::stringstream;
19 : using std::transform;
20 : using std::setfill;
21 : using std::setw;
22 : using std::setprecision;
23 : using pcf::TimeStamp;
24 :
25 : ////////////////////////////////////////////////////////////////////////////////
26 : /// Standard constructor - initialize the internal timeval struct.
27 :
28 7551 : TimeStamp::TimeStamp()
29 : {
30 7551 : m_tvCurr = TimeStamp::now().getTimeVal();
31 7551 : }
32 :
33 : ////////////////////////////////////////////////////////////////////////////////
34 : /// Standard constructor from a timeval structure.
35 : /// @param tvCurr A timeval struct which contains a valid time.
36 :
37 7897 : TimeStamp::TimeStamp( const timeval &tvCurr )
38 : {
39 7897 : m_tvCurr.tv_sec = tvCurr.tv_sec;
40 7897 : m_tvCurr.tv_usec = tvCurr.tv_usec;
41 7897 : }
42 :
43 : ////////////////////////////////////////////////////////////////////////////////
44 : /// Standard constructor from a number of milliseconds. The amount is
45 : /// considered to be an absolute value.
46 : /// @param nMillis The number of milliseconds since the epoch UTC.
47 :
48 0 : TimeStamp::TimeStamp( const int &nMillis )
49 : {
50 0 : m_tvCurr.tv_sec = nMillis / 1000;
51 0 : m_tvCurr.tv_usec = ( nMillis % 1000 ) * 1000;
52 0 : }
53 :
54 : ////////////////////////////////////////////////////////////////////////////////
55 : /// standard constructor from a year, month, day, hour (24), min, sec. The
56 : /// time is considered to be in UTC, and no adjustment is done.
57 : /// @param nYear The 4 digit year.
58 : /// @param nMonth The month (between 1 and 12 inclusive).
59 : /// @param nDay The day (between 1 and 31 inclusive).
60 : /// @param nHour The hour (between 0 and 23 inclusive).
61 : /// @param nMinute The minute (between 0 and 59 inclusive)
62 : /// @param nSecond The second (between 0 and 60 inclusive).
63 :
64 0 : TimeStamp::TimeStamp( const int &nYear, const int &nMonth, const int &nDay,
65 0 : const int &nHour, const int &nMinute, const int &nSecond )
66 : {
67 : // First get the current UTC. This will be modified to hold the
68 : // specified timestamp.
69 0 : ::time_t now = ::time( 0 );
70 0 : ::tm *gmtm = ::gmtime( &now );
71 :
72 : // Now fill in the rest of the struct with our desired values.
73 0 : gmtm->tm_sec = nSecond;
74 0 : gmtm->tm_min = nMinute;
75 0 : gmtm->tm_hour = nHour;
76 0 : gmtm->tm_mday = nDay;
77 0 : gmtm->tm_mon = nMonth - 1; // month is zero-based in tm struct.
78 0 : gmtm->tm_year = nYear - 1900; // 1900 is stored as 0 in tm struct.
79 : //gmtm->tm_wday; /* day of week (Sunday = 0) */
80 : //gmtm->tm_yday; /* day of year (0 - 365) */
81 : //gmtm->tm_isdst; /* is summer time in effect? */
82 : //gmtm->tm_zone; /* abbreviation of timezone name */
83 : //gmtm->tm_gmtoff; /* offset from UTC in seconds */
84 :
85 : // The object pointed by gmtm is modified, setting the tm_wday and tm_yday
86 : // to their appropiate values, and modifying the other members as necessary
87 : // to values within the normal range representing the specified time.
88 0 : m_tvCurr.tv_sec = local_timegm( gmtm );
89 0 : m_tvCurr.tv_usec = 0;
90 0 : }
91 :
92 : ////////////////////////////////////////////////////////////////////////////////
93 : /// Standard destructor.
94 :
95 15541 : TimeStamp::~TimeStamp()
96 : {
97 : // nothing to do.
98 15541 : }
99 :
100 : ////////////////////////////////////////////////////////////////////////////////
101 : /// Returns the underlying timeval struct. This is the number of seconds since
102 : /// January 1, 1970, UTC.
103 :
104 7551 : const timeval &TimeStamp::getTimeVal() const
105 : {
106 7551 : return m_tvCurr;
107 : }
108 :
109 : ////////////////////////////////////////////////////////////////////////////////
110 : /// Returns the microsecond part of the time val struct.
111 :
112 : /*int TimeStamp::getTimeValMicros() const
113 : {
114 : return m_tvCurr.tv_usec;
115 : }*/
116 :
117 : ////////////////////////////////////////////////////////////////////////////////
118 : /// Returns the seconds part of the time val struct.
119 :
120 : /*int TimeStamp::getTimeValSecs() const
121 : {
122 : return m_tvCurr.tv_sec;
123 : }*/
124 :
125 : ////////////////////////////////////////////////////////////////////////////////
126 : /// Assignment operator. Assigns this object from another TimeStamp object.
127 : /// @param tsRhs The TimeStamp object to use to reset this one.
128 :
129 392 : const TimeStamp &TimeStamp::operator= ( const TimeStamp &tsRhs )
130 : {
131 392 : if ( &tsRhs != this )
132 : {
133 392 : m_tvCurr = tsRhs.m_tvCurr;
134 : }
135 392 : return *this;
136 : }
137 :
138 : ////////////////////////////////////////////////////////////////////////////////
139 : /// Assignment operator from a timeval. Sets the internal data from a timeval
140 : /// struct
141 : /// @param tv The timeval struct to use.
142 :
143 0 : const TimeStamp &TimeStamp::operator= ( const timeval &tv )
144 : {
145 0 : m_tvCurr.tv_sec = tv.tv_sec;
146 0 : m_tvCurr.tv_usec = tv.tv_usec;
147 :
148 0 : return *this;
149 : }
150 :
151 : ////////////////////////////////////////////////////////////////////////////////
152 : /// Assignment operator from a number of milliseconds. This is considered to be
153 : /// an absolute value counted from the epoch, UTC.
154 : /// @param nMillis The number of milliseconds that has elapsed since epoch, UTC.
155 :
156 0 : const TimeStamp &TimeStamp::operator= ( const int &nMillis )
157 : {
158 0 : m_tvCurr.tv_sec = nMillis / 1000;
159 0 : m_tvCurr.tv_usec = ( nMillis % 1000 ) * 1000;
160 :
161 0 : return *this;
162 : }
163 :
164 : ////////////////////////////////////////////////////////////////////////////////
165 : /// Subtraction operator. Subtracts two TimeStamps and returns the difference
166 : /// as another TimeStamp. One must exercise caution, as the result is not an
167 : /// absolute time, but rather a relative one.
168 : /// @param tsRhs Another TimeStamp object.
169 : /// @return The result: an absolute TimeStamp object.
170 :
171 12 : TimeStamp TimeStamp::operator- ( const TimeStamp &tsRhs ) const
172 : {
173 : // subtracting two timeval structs is a little non-obvious.
174 :
175 : timeval tvDiff;
176 :
177 12 : tvDiff.tv_sec = m_tvCurr.tv_sec - tsRhs.m_tvCurr.tv_sec;
178 12 : tvDiff.tv_usec = m_tvCurr.tv_usec - tsRhs.m_tvCurr.tv_usec;
179 12 : if ( tvDiff.tv_usec < 0 )
180 : {
181 0 : tvDiff.tv_sec--;
182 0 : tvDiff.tv_usec += 1000000;
183 : }
184 :
185 24 : return TimeStamp( tvDiff );
186 : }
187 :
188 : ////////////////////////////////////////////////////////////////////////////////
189 : /// Addition operator. Adds two TimeStamps and returns the sum
190 : /// as another TimeStamp. One must exercise caution, as the second may not
191 : /// be a meaningful value.
192 : /// @param tsRhs Another TimeStamp object.
193 : /// @return The result: an absolute TimeStamp object.
194 :
195 0 : TimeStamp TimeStamp::operator+ ( const TimeStamp &tsRhs ) const
196 : {
197 : // adding two timeval structs is a little non-obvious.
198 :
199 : timeval tvSum;
200 0 : tvSum.tv_sec = m_tvCurr.tv_sec + tsRhs.m_tvCurr.tv_sec;
201 0 : int nnSum = m_tvCurr.tv_usec + tsRhs.m_tvCurr.tv_usec;
202 :
203 0 : if ( nnSum < 1000000 )
204 : {
205 0 : tvSum.tv_usec = nnSum;
206 : }
207 : else
208 : {
209 0 : tvSum.tv_sec++;
210 0 : tvSum.tv_usec = nnSum - 1000000;
211 : }
212 :
213 0 : return TimeStamp( tvSum );
214 : }
215 :
216 : ////////////////////////////////////////////////////////////////////////////////
217 : /// Less than operator. Subtracts two TimeStamps and returns true if this
218 : /// object is less than (further in the past) than tsRhs.
219 : /// @param tsRhs Another TimeStamp object.
220 : /// @return true or false.
221 :
222 0 : bool TimeStamp::operator<( const TimeStamp &tsRhs ) const
223 : {
224 0 : return ( ( getMicros() - tsRhs.getMicros() ) < 0 );
225 : }
226 :
227 : ////////////////////////////////////////////////////////////////////////////////
228 : /// Less than or equal to operator. Subtracts two TimeStamps and returns
229 : /// true if this object is less than (further in the past) or equal to than tsRhs.
230 : /// @param tsRhs Another TimeStamp object.
231 : /// @return true or false.
232 :
233 0 : bool TimeStamp::operator<=( const TimeStamp &tsRhs ) const
234 : {
235 0 : return ( ( getMicros() - tsRhs.getMicros() ) <= 0 );
236 : }
237 :
238 : ////////////////////////////////////////////////////////////////////////////////
239 : /// Greater than operator. Subtracts two TimeStamps and returns true if this
240 : /// object is greater than (more recent in the past) than tsRhs.
241 : /// @param tsRhs Another TimeStamp object.
242 : /// @return true or false.
243 :
244 0 : bool TimeStamp::operator>( const TimeStamp &tsRhs ) const
245 : {
246 0 : return ( ( getMicros() - tsRhs.getMicros() ) > 0 );
247 : }
248 :
249 : ////////////////////////////////////////////////////////////////////////////////
250 : /// Greater than or equal to operator. Subtracts two TimeStamps and returns
251 : /// true if this object is greater than (more recent in the past) or equal to
252 : /// the tsRhs.
253 : /// @param tsRhs Another TimeStamp object.
254 : /// @return true or false.
255 :
256 0 : bool TimeStamp::operator>=( const TimeStamp &tsRhs ) const
257 : {
258 0 : return ( ( getMicros() - tsRhs.getMicros() ) >= 0 );
259 : }
260 :
261 : ////////////////////////////////////////////////////////////////////////////////
262 : /// Copy constructor. Initialize this TimeStamp from another one.
263 : /// @param ts Another TimeStamp to use to initialize this one.
264 :
265 93 : TimeStamp::TimeStamp( const TimeStamp &ts )
266 : {
267 93 : m_tvCurr = ts.m_tvCurr;
268 93 : }
269 :
270 : ////////////////////////////////////////////////////////////////////////////////
271 : /// Equals operator. Returns true if the two TimeStamp objects are the same.
272 : /// @param tsRhs Another TimeStamp object.
273 : /// @return True if the two TimeStamps are the same, false otherwise.
274 :
275 0 : bool TimeStamp::operator== ( const TimeStamp &tsRhs ) const
276 : {
277 0 : return bool( m_tvCurr.tv_sec == tsRhs.m_tvCurr.tv_sec &&
278 0 : m_tvCurr.tv_usec == tsRhs.m_tvCurr.tv_usec );
279 : }
280 :
281 : ////////////////////////////////////////////////////////////////////////////////
282 : /// returns the month number (1 to 12) given the 3-letter name.
283 : /// The name should be one of: jan feb mar apr may jun jul aug sep oct nov dec.
284 : /// Capitalization will be corrected. It defaults to -1 if it is unknown.
285 :
286 0 : int TimeStamp::getMonthNumber( const std::string &szMonth )
287 : {
288 0 : string szMonthLC = szMonth.substr( 0, 3 );
289 0 : transform( szMonthLC.begin(), szMonthLC.end(), szMonthLC.begin(),
290 : ( int( * )( int ) )tolower );
291 :
292 0 : if ( szMonthLC == "jan" )
293 0 : return 1;
294 0 : if ( szMonthLC == "feb" )
295 0 : return 2;
296 0 : if ( szMonthLC == "mar" )
297 0 : return 3;
298 0 : if ( szMonthLC == "apr" )
299 0 : return 4;
300 0 : if ( szMonthLC == "may" )
301 0 : return 5;
302 0 : if ( szMonthLC == "jun" )
303 0 : return 6;
304 0 : if ( szMonthLC == "jul" )
305 0 : return 7;
306 0 : if ( szMonthLC == "aug" )
307 0 : return 8;
308 0 : if ( szMonthLC == "sep" )
309 0 : return 9;
310 0 : if ( szMonthLC == "oct" )
311 0 : return 10;
312 0 : if ( szMonthLC == "nov" )
313 0 : return 11;
314 0 : if ( szMonthLC == "dec" )
315 0 : return 12;
316 : // default is unknown.
317 0 : return -1;
318 0 : }
319 :
320 : ////////////////////////////////////////////////////////////////////////////////
321 : /// Returns the 3-letter weekday name given the number (1 to 7) of the weekday.
322 : /// The name will be one of: Sun Mon Tue Wed Thu Fri Sat.
323 : /// Capitalization will be corrected. It defaults to "???" if it is unknown.
324 :
325 0 : string TimeStamp::getWeekdayName( const int &nWeekdayNum )
326 : {
327 0 : switch ( nWeekdayNum )
328 : {
329 0 : case 1:
330 0 : return "Sun";
331 : break;
332 0 : case 2:
333 0 : return "Mon";
334 : break;
335 0 : case 3:
336 0 : return "Tue";
337 : break;
338 0 : case 4:
339 0 : return "Wed";
340 : break;
341 0 : case 5:
342 0 : return "Thu";
343 : break;
344 0 : case 6:
345 0 : return "Fri";
346 : break;
347 0 : case 7:
348 0 : return "Sat";
349 : break;
350 0 : default:
351 0 : return "???";
352 : break;
353 : }
354 : }
355 :
356 : ////////////////////////////////////////////////////////////////////////////////
357 : /// Returns the 3-letter month name given the number (1 to 12) of the month.
358 : /// The name will be one of: Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec.
359 : /// Capitalization will be corrected. It defaults to "???" if it is unknown.
360 :
361 0 : string TimeStamp::getMonthName( const int &nMonthNum )
362 : {
363 0 : switch ( nMonthNum )
364 : {
365 0 : case 1:
366 0 : return "Jan";
367 : break;
368 0 : case 2:
369 0 : return "Feb";
370 : break;
371 0 : case 3:
372 0 : return "Mar";
373 : break;
374 0 : case 4:
375 0 : return "Apr";
376 : break;
377 0 : case 5:
378 0 : return "May";
379 : break;
380 0 : case 6:
381 0 : return "Jun";
382 : break;
383 0 : case 7:
384 0 : return "Jul";
385 : break;
386 0 : case 8:
387 0 : return "Aug";
388 : break;
389 0 : case 9:
390 0 : return "Sep";
391 : break;
392 0 : case 10:
393 0 : return "Oct";
394 : break;
395 0 : case 11:
396 0 : return "Nov";
397 : break;
398 0 : case 12:
399 0 : return "Dec";
400 : break;
401 0 : default:
402 0 : return "???";
403 : break;
404 : }
405 : }
406 :
407 : ////////////////////////////////////////////////////////////////////////////////
408 : /// Fetches the current time from the system. This can be used to initialize
409 : /// an instance of this object: TimeStamp ts = TimeStamp::now();. It can
410 : /// also be used when just the current itme is needed. UTC is assumed.
411 : /// @return A TimeStamp object containing the current system time.
412 :
413 7859 : TimeStamp TimeStamp::now()
414 : {
415 : timeval tvCurr;
416 :
417 : #ifdef WIN32
418 : FILETIME ftNow;
419 : GetSystemTimeAsFileTime ( &ftNow );
420 : long long nnTime = ( long long ) ftNow.dwHighDateTime << 32;
421 : nnTime |= ftNow.dwLowDateTime;
422 : /// convert from 100 nanosec to 1 usec.
423 : nnTime /= 10;
424 : /// Number of microsec between the beginning of the Windows epoch
425 : /// (1 Jan 1601) and the Unix epoch (1 Jan 1970).
426 : nnTime -= 11644473600000000ULL;
427 : tvCurr.tv_sec = ( nnTime / 1000000ULL );
428 : tvCurr.tv_usec = ( nnTime % 1000000ULL );
429 : #else
430 : /**
431 : The gettimeofday() function shall obtain the current time, expressed
432 : as seconds and microseconds since the Epoch, UTC, and store it in the
433 : timeval structure pointed to by tp. The resolution of the system clock
434 : is unspecified. The gettimeofday() function shall return 0 and no
435 : value shall be reserved to indicate an error.
436 : If tzp is not a null pointer, the behavior is unspecified.
437 : **/
438 7859 : ::gettimeofday( &tvCurr, NULL );
439 : #endif
440 :
441 15718 : return TimeStamp( tvCurr );
442 : }
443 :
444 : ////////////////////////////////////////////////////////////////////////////////
445 : /// Creates an iso-formatted time similar to: 193812 based on the currently
446 : /// stored time.
447 : /// @return the iso-formatted number.
448 :
449 0 : string TimeStamp::getFormattedIsoTimeStr() const
450 : {
451 0 : string szFormatted = "000000";
452 :
453 0 : time_t tNumSecs = getTimeValSecs();
454 0 : tm *tmCurr = ::gmtime( &tNumSecs );
455 :
456 : // transform date and time to broken-down time.
457 0 : if ( tmCurr != NULL )
458 : {
459 0 : stringstream ssFormatted;
460 : ssFormatted
461 0 : << setfill( '0' ) << setw( 2 ) << tmCurr->tm_hour
462 0 : << setfill( '0' ) << setw( 2 ) << tmCurr->tm_min
463 0 : << setfill( '0' ) << setw( 2 ) << tmCurr->tm_sec;
464 0 : szFormatted = ssFormatted.str();
465 0 : }
466 :
467 0 : return szFormatted;
468 0 : }
469 :
470 : ////////////////////////////////////////////////////////////////////////////////
471 : /// Generates the date and time formatted as "Sun Jun 24 19:38:12.234 2007".
472 : /// @return A string formatted with the date and time information.
473 :
474 0 : string TimeStamp::getFormattedStr() const
475 : {
476 0 : string szFormatted = "??? ??? 00 00:00:00.000 0000";
477 :
478 0 : time_t tNumSecs = getTimeValSecs();
479 0 : int nNumMillis = getTimeValMicros() / 1000;
480 0 : tm *tmCurr = ::gmtime( &tNumSecs );
481 :
482 : // transform date and time to broken-down time.
483 0 : if ( tmCurr != NULL )
484 : {
485 0 : stringstream ssFormatted;
486 : ssFormatted
487 0 : << getWeekdayName( tmCurr->tm_wday + 1 )
488 : << " "
489 0 : << getMonthName( tmCurr->tm_mon + 1 )
490 : << " "
491 0 : << setfill( '0' ) << setw( 2 ) << tmCurr->tm_mday
492 : << " "
493 0 : << setfill( '0' ) << setw( 2 ) << tmCurr->tm_hour
494 : << ":"
495 0 : << setfill( '0' ) << setw( 2 ) << tmCurr->tm_min
496 : << ":"
497 0 : << setfill( '0' ) << setw( 2 ) << tmCurr->tm_sec
498 : << "."
499 0 : << setfill( '0' ) << setw( 3 ) << nNumMillis
500 : << " "
501 0 : << setfill( '0' ) << setw( 4 ) << 1900 + tmCurr->tm_year;
502 0 : szFormatted = ssFormatted.str();
503 0 : }
504 :
505 0 : return szFormatted;
506 0 : }
507 :
508 : ////////////////////////////////////////////////////////////////////////////////
509 : /// Creates an iso-formatted date similar to:
510 : /// YYYY-MM-DDThh:mm:ss.sTZD (eg 1997-07-16T19:20:30.451Z)
511 : /// Based on the current time.
512 : /// @return the iso-formatted string.
513 :
514 0 : string TimeStamp::getFormattedIso8601Str() const
515 : {
516 0 : string szFormatted = "0000-00-00T00:00:00.000000Z";
517 :
518 : // It is a bit roundabout, but this is the simpliest way I have found
519 : // to convert a timeval to a tm.
520 0 : time_t tNumSecs = getTimeValSecs();
521 0 : int nNumMicros = getTimeValMicros();
522 0 : tm *tmCurr = ::gmtime( &tNumSecs );
523 :
524 : // transform date and time to broken-down time.
525 0 : if ( tmCurr != NULL )
526 : {
527 0 : stringstream ssFormatted;
528 : ssFormatted
529 0 : << setfill( '0' ) << setw( 4 ) << 1900 + tmCurr->tm_year
530 : << "-"
531 0 : << setfill( '0' ) << setw( 2 ) << 1 + tmCurr->tm_mon
532 : << "-"
533 0 : << setfill( '0' ) << setw( 2 ) << tmCurr->tm_mday
534 : << "T"
535 0 : << setfill( '0' ) << setw( 2 ) << tmCurr->tm_hour
536 : << ":"
537 0 : << setfill( '0' ) << setw( 2 ) << tmCurr->tm_min
538 : << ":"
539 0 : << setfill( '0' ) << setw( 2 ) << tmCurr->tm_sec
540 : << "."
541 0 : << setfill( '0' ) << setw( 6 ) << nNumMicros
542 0 : << "Z";
543 0 : szFormatted = ssFormatted.str();
544 0 : }
545 :
546 0 : return szFormatted;
547 0 : }
548 :
549 : ////////////////////////////////////////////////////////////////////////////////
550 : /// Creates an iso-formatted date similar to: 20091230 based on the currently
551 : /// stored time.
552 : /// @return the iso-formatted number.
553 :
554 0 : string TimeStamp::getFormattedIsoDateStr() const
555 : {
556 0 : string szFormatted = "00000000";
557 :
558 0 : time_t tNumSecs = getTimeValSecs();
559 0 : tm *tmCurr = ::gmtime( &tNumSecs );
560 :
561 : // transform date and time to broken-down time.
562 0 : if ( tmCurr != NULL )
563 : {
564 0 : stringstream ssFormatted;
565 : ssFormatted
566 0 : << setfill( '0' ) << setw( 4 ) << 1900 + tmCurr->tm_year
567 0 : << setfill( '0' ) << setw( 2 ) << 1 + tmCurr->tm_mon
568 0 : << setfill( '0' ) << setw( 2 ) << tmCurr->tm_mday;
569 0 : szFormatted = ssFormatted.str();
570 0 : }
571 :
572 0 : return szFormatted;
573 0 : }
574 :
575 : ////////////////////////////////////////////////////////////////////////////////
576 : /// Calculates the number of milliseconds that have elapsed since this object's
577 : /// internal data was set and the time stamp ts.
578 : /// @return The number of milliseconds that have elapsed since the object
579 : /// was created or updated (see 'update').
580 :
581 12 : double TimeStamp::elapsedMillis( const TimeStamp &ts ) const
582 : {
583 12 : TimeStamp tsDiff = ts - *this;
584 24 : return tsDiff.getMillis();
585 12 : }
586 :
587 : ////////////////////////////////////////////////////////////////////////////////
588 : /// Calculates the number of milliseconds that have elapsed since this object's
589 : /// internal data was set and the time stamp ts. Resets the timestamp to
590 : /// the current time if the interval has passsed.
591 : /// @return The number of milliseconds that have elapsed since the object
592 : /// was created or updated (see 'update').
593 :
594 0 : bool TimeStamp::intervalElapsedMillis( const int iInterval )
595 : {
596 0 : TimeStamp tsCurrent = TimeStamp::now();
597 0 : TimeStamp tsDiff = tsCurrent - *this;
598 0 : bool oIntervalElapsed = ( tsDiff.getMillis() >= iInterval );
599 0 : if ( oIntervalElapsed )
600 0 : *this = tsCurrent;
601 0 : return oIntervalElapsed;
602 0 : }
603 :
604 : ////////////////////////////////////////////////////////////////////////////////
605 : /// Calculates the number of days that have elapsed since this object's
606 : /// internal data was set and the time stamp ts.
607 : /// @return The number of milliseconds that have elapsed since the object
608 : /// was created or updated (see 'update').
609 :
610 0 : double TimeStamp::elapsedDays( const TimeStamp &ts ) const
611 : {
612 0 : TimeStamp tsDiff = ts - *this;
613 0 : return tsDiff.getDays();
614 0 : }
615 :
616 : ////////////////////////////////////////////////////////////////////////////////
617 : /// Calculates the number of microseconds since epoch (1970 Jan 1), UTC.
618 : /// @return The number of microseconds since the unix epoch.
619 :
620 0 : double TimeStamp::getMicros() const
621 : {
622 0 : return ( static_cast<double>( m_tvCurr.tv_sec ) * 1000000.0 )
623 0 : + ( static_cast<double>( m_tvCurr.tv_usec ) );
624 : }
625 :
626 : ////////////////////////////////////////////////////////////////////////////////
627 : /// Calculates the number of milliseconds since epoch (1970 Jan 1), UTC.
628 : /// @return The number of milliseconds since the unix epoch.
629 :
630 12 : double TimeStamp::getMillis() const
631 : {
632 12 : return ( static_cast<double>( m_tvCurr.tv_sec ) * 1000.0 )
633 12 : + ( static_cast<double>( m_tvCurr.tv_usec ) / 1000.0 );
634 : }
635 :
636 : ////////////////////////////////////////////////////////////////////////////////
637 : /// Calculates the number of days since epoch (1970 Jan 1), UTC.
638 : /// @return The number of days since the unix epoch.
639 :
640 0 : double TimeStamp::getDays() const
641 : {
642 : // There are 86400 seconds in one day.
643 0 : return ( static_cast<double>( m_tvCurr.tv_sec )
644 0 : + static_cast<double>( m_tvCurr.tv_usec ) / 1000000.0 ) / 86400.0;
645 : }
646 :
647 : ////////////////////////////////////////////////////////////////////////////////
648 : /// Generates the year (1900+) from the current time. If there is
649 : /// an error, numeric_limits<unsigned int>::max() is returned.
650 :
651 0 : unsigned int TimeStamp::getYear() const
652 : {
653 0 : unsigned int uiYear = std::numeric_limits<unsigned int>::max();
654 :
655 0 : time_t tNumSecs = getTimeValSecs();
656 0 : tm *tmCurr = ::gmtime( &tNumSecs );
657 :
658 0 : if ( tmCurr != NULL )
659 : {
660 0 : uiYear = static_cast<unsigned int>( 1900 + tmCurr->tm_year );
661 : }
662 :
663 0 : return uiYear;
664 : }
665 :
666 : ////////////////////////////////////////////////////////////////////////////////
667 : /// Generates the year's month number (1-12) from the current time. If there is
668 : /// an error, std::numeric_limits<unsigned int>::max() is returned.
669 :
670 0 : unsigned int TimeStamp::getYearMonth() const
671 : {
672 0 : unsigned int uiMonth = std::numeric_limits<unsigned int>::max();
673 :
674 0 : time_t tNumSecs = getTimeValSecs();
675 0 : tm *tmCurr = ::gmtime( &tNumSecs );
676 :
677 0 : if ( tmCurr != NULL )
678 : {
679 0 : uiMonth = static_cast<unsigned int>( tmCurr->tm_mon + 1 );
680 : }
681 :
682 0 : return uiMonth;
683 : }
684 :
685 : ////////////////////////////////////////////////////////////////////////////////
686 : /// Generates the day of the month (1-31) from the current time. If there is
687 : /// an error, numeric_limits<unsigned int>::max() is returned.
688 :
689 0 : unsigned int TimeStamp::getMonthDay() const
690 : {
691 0 : unsigned int uiDay = std::numeric_limits<unsigned int>::max();
692 :
693 0 : time_t tNumSecs = getTimeValSecs();
694 0 : tm *tmCurr = ::gmtime( &tNumSecs );
695 :
696 0 : if ( tmCurr != NULL )
697 : {
698 0 : uiDay = static_cast<unsigned int>( tmCurr->tm_mday );
699 : }
700 :
701 0 : return uiDay;
702 : }
703 :
704 : ////////////////////////////////////////////////////////////////////////////////
705 : /// Generates the hour of the day (0-23) from the current time. If there is
706 : /// an error, numeric_limits<unsigned int>::max() is returned.
707 :
708 0 : unsigned int TimeStamp::getDayHour() const
709 : {
710 0 : unsigned int uiHour = std::numeric_limits<unsigned int>::max();
711 :
712 0 : time_t tNumSecs = getTimeValSecs();
713 0 : tm *tmCurr = ::gmtime( &tNumSecs );
714 :
715 0 : if ( tmCurr != NULL )
716 : {
717 0 : uiHour = static_cast<unsigned int>( tmCurr->tm_hour );
718 : }
719 :
720 0 : return uiHour;
721 : }
722 :
723 : ////////////////////////////////////////////////////////////////////////////////
724 : /// Generates the minute of the hour (0-59) from the current time. If there is
725 : /// an error, numeric_limits<unsigned int>::max() is returned.
726 :
727 0 : unsigned int TimeStamp::getHourMinute() const
728 : {
729 0 : unsigned int uiMinute = std::numeric_limits<unsigned int>::max();
730 :
731 0 : time_t tNumSecs = getTimeValSecs();
732 0 : tm *tmCurr = ::gmtime( &tNumSecs );
733 :
734 0 : if ( tmCurr != NULL )
735 : {
736 0 : uiMinute = static_cast<unsigned int>( tmCurr->tm_min );
737 : }
738 :
739 0 : return uiMinute;
740 : }
741 :
742 : ////////////////////////////////////////////////////////////////////////////////
743 : /// Generates the second of the minute (0-60) from the current time. If there is
744 : /// an error, numeric_limits<unsigned int>::max() is returned.
745 :
746 0 : unsigned int TimeStamp::getMinuteSecond() const
747 : {
748 0 : unsigned int uiSecond = std::numeric_limits<unsigned int>::max();
749 :
750 0 : time_t tNumSecs = getTimeValSecs();
751 0 : tm *tmCurr = ::gmtime( &tNumSecs );
752 :
753 0 : if ( tmCurr != NULL )
754 : {
755 0 : uiSecond = static_cast<unsigned int>( tmCurr->tm_sec );
756 : }
757 :
758 0 : return uiSecond;
759 : }
760 :
761 : ////////////////////////////////////////////////////////////////////////////////
762 : /// Generates the millisecond of the second (0-999) from the current time.
763 :
764 0 : unsigned int TimeStamp::getSecondMillisecond() const
765 : {
766 0 : unsigned int uiMillisecond = getTimeValMicros() / 1000;
767 :
768 0 : return uiMillisecond;
769 : }
770 :
771 : ////////////////////////////////////////////////////////////////////////////////
772 : /// Decrement the time stamp one day.
773 :
774 0 : void TimeStamp::decrementDay()
775 : {
776 : // There are 86400 seconds in one day.
777 0 : m_tvCurr.tv_sec -= 86400;
778 0 : }
779 :
780 : ////////////////////////////////////////////////////////////////////////////////
781 : /// Increment the time stamp one day.
782 :
783 0 : void TimeStamp::incrementDay()
784 : {
785 : // There are 86400 seconds in one day.
786 0 : m_tvCurr.tv_sec += 86400;
787 0 : }
788 :
789 : ////////////////////////////////////////////////////////////////////////////////
790 : /// Creates a string filled with number of microseconds since epoch
791 : /// (1970 Jan 1), UTC. See 'getMicros' for details about the returned value.
792 : /// @return The number of microseconds since the unix epoch.
793 :
794 0 : string TimeStamp::getMicrosStr() const
795 : {
796 0 : stringstream ssValue;
797 0 : ssValue << getMicros();
798 0 : return ssValue.str();
799 0 : }
800 :
801 : ////////////////////////////////////////////////////////////////////////////////
802 : /// Creates a string filled with number of milliseconds since epoch
803 : /// (1970 Jan 1), UTC. See 'getMillis' for details about the returned value.
804 : /// @return The number of milliseconds since the unix epoch.
805 :
806 0 : string TimeStamp::getMillisStr() const
807 : {
808 0 : stringstream ssValue;
809 0 : ssValue << getMillis();
810 0 : return ssValue.str();
811 0 : }
812 :
813 : ////////////////////////////////////////////////////////////////////////////////
814 : /// Assigns the internal timeval from an MJD number. See 'setMJD" to understand
815 : /// the format of the MJD. The time is in UTC.
816 : /// @param xMJD The Modified Julian Day number. The fractional part holds
817 : /// partial days.
818 :
819 0 : void TimeStamp::fromMJD( const double &xMJD )
820 : {
821 : /// adjust this day count to start on 1 Jan 1970.
822 0 : double xDays = xMJD - 40587.0;
823 :
824 : /// convert to a number of seconds.
825 0 : long long nnSecs = static_cast<long long>( xDays * 86400.0 );
826 :
827 : /// get the number of microsecs.
828 0 : m_tvCurr.tv_usec = static_cast<long long>(
829 0 : ( xDays * 86400.0 - static_cast<double>( nnSecs ) ) * 1000000.0 );
830 :
831 0 : m_tvCurr.tv_sec = nnSecs;
832 0 : }
833 :
834 : ////////////////////////////////////////////////////////////////////////////////
835 : /// Sets the internal time from a ISO 8601 formatted string. UTC is assumed.
836 : /// @param szIso8601 a string like: "2013-09-23T11:41:40.959453Z"
837 :
838 0 : void TimeStamp::fromFormattedIso8601Str( const string &szIso8601 )
839 : {
840 : /*
841 : string szIso8601Mod = szIso8601;
842 :
843 : // We need some speed here, so change this to happen in one loop.
844 : for ( unsigned int ii = 0; ii < szIso8601Mod.size(); ii++ )
845 : {
846 : if ( szIso8601Mod[ii] == '-' || szIso8601Mod[ii] == 'T' ||
847 : szIso8601Mod[ii] == ':' || szIso8601Mod[ii] == '.' ||
848 : szIso8601Mod[ii] == 'Z' )
849 : szIso8601Mod[ii] = ' ';
850 : }
851 : //std::replace( szIso8601Mod.begin(), szIso8601Mod.end(), '-', ' ' );
852 : //std::replace( szIso8601Mod.begin(), szIso8601Mod.end(), 'T', ' ' );
853 : //std::replace( szIso8601Mod.begin(), szIso8601Mod.end(), ':', ' ' );
854 : //std::replace( szIso8601Mod.begin(), szIso8601Mod.end(), '.', ' ' );
855 : //std::replace( szIso8601Mod.begin(), szIso8601Mod.end(), 'Z', ' ' );
856 :
857 : stringstream ssCurr;
858 : ssCurr.str( szIso8601Mod );
859 :
860 : tm tmCurr;
861 : int nYear, nMonth, nDay, nHour, nMinute, nSecond, nMicros;
862 :
863 : ssCurr >> nYear >> nMonth >> nDay >> nHour >> nMinute >> nSecond >> nMicros;
864 : */
865 : tm tmCurr;
866 : int nYear, nMonth, nDay, nHour, nMinute, nSecond, nMicros;
867 0 : ::sscanf( szIso8601.c_str(), "%d-%d-%dT%d:%d:%d.%dZ",
868 : &nYear, &nMonth, &nDay, &nHour, &nMinute, &nSecond, &nMicros );
869 :
870 0 : tmCurr.tm_year = nYear - 1900;
871 0 : tmCurr.tm_mon = nMonth - 1;
872 0 : tmCurr.tm_mday = nDay;
873 0 : tmCurr.tm_hour = nHour;
874 0 : tmCurr.tm_min = nMinute;
875 0 : tmCurr.tm_sec = nSecond;
876 :
877 : //JRM changed to timegm from local_timegm
878 0 : m_tvCurr.tv_sec = long( timegm( &tmCurr ) );
879 0 : m_tvCurr.tv_usec = nMicros;
880 0 : }
881 :
882 : ////////////////////////////////////////////////////////////////////////////////
883 : /// Generates a string representing the Modified Julian Day number (MJD).
884 : /// This day count has been adjusted to start on 17 November 1858. This day
885 : /// corresponds to MJD 2400000, and is generally accepted as 0, since the
886 : /// "24" will not change for three centuries to "25".
887 : /// @return A double which contains the day number and any fraction of a day
888 : /// which has elapsed.
889 :
890 0 : double TimeStamp::getMJD() const
891 : {
892 : /// first, get the number of days (and fractions of a day) since unix epoch.
893 0 : double xDays = ( static_cast<double>( m_tvCurr.tv_sec ) +
894 0 : ( static_cast<double>( m_tvCurr.tv_usec ) / 1000000.0 ) ) / 86400.0;
895 :
896 : /// adjust this day count to start on 17 November 1858. This day corresponds
897 : /// to MJD 2400000, and is generally accepted as 0, since the "24" will not
898 : /// change for three centuries to "25".
899 0 : return xDays + 40587.0;
900 : }
901 :
902 : ////////////////////////////////////////////////////////////////////////////////
903 : /// 'timegm' is nonstandard at this time, so our own version is implemented
904 :
905 0 : ::time_t TimeStamp::local_timegm( ::tm *tmCurr )
906 : {
907 : ::time_t tUtc;
908 : char *pcTz;
909 :
910 : // Get the current time zone. This will be null if it does not exist.
911 0 : pcTz = ::getenv( "TZ" );
912 :
913 : // Set the time zone to be UTC.
914 0 : ::setenv( "TZ", "UTC0", 1 );
915 0 : ::tzset();
916 :
917 : // Make a UTC time. (time in the UTC time zone).
918 0 : tUtc = ::mktime( tmCurr );
919 :
920 : // Set the time zone back, or delete it if it did not exist.
921 0 : if ( pcTz != NULL )
922 0 : ::setenv( "TZ", pcTz, 1 );
923 : else
924 0 : ::unsetenv( "TZ" );
925 0 : :: tzset();
926 :
927 0 : return tUtc;
928 : }
929 :
930 : ////////////////////////////////////////////////////
931 : ////////////////////////////
932 : /// Handles streaming the TimeStamp formatted string. See 'getFormattedStr'
933 : /// for details about the format of the string.
934 : /// @param strmOut The stream to be written to.
935 : /// @param tsRhs The TimeStamp to be streamed.
936 : /// @return The modified stream that has been written to.
937 :
938 0 : ostream &operator<< ( ostream &strmOut, const TimeStamp &tsRhs )
939 : {
940 0 : strmOut << tsRhs.getFormattedStr();
941 0 : return strmOut;
942 : }
943 :
944 : ////////////////////////////////////////////////////////////////////////////////
|