Newer
Older
Janik Zikovsky
committed
#include <time.h>
namespace Mantid
{
namespace Kernel
{
Janik Zikovsky
committed
/// Max allowed nanoseconds in the time; 2^62-1
static int64_t MAX_NANOSECONDS = 4611686018427387903LL;
Janik Zikovsky
committed
/// Max allowed seconds in the time
static int64_t MAX_SECONDS = 4611686017LL;
Janik Zikovsky
committed
/// Min allowed nanoseconds in the time; -2^62+1
static int64_t MIN_NANOSECONDS = -4611686018427387903LL;
Janik Zikovsky
committed
/// Min allowed seconds in the time
static int64_t MIN_SECONDS = -4611686017LL;
Janik Zikovsky
committed
namespace DateAndTimeHelpers
Janik Zikovsky
committed
{
Janik Zikovsky
committed
//-----------------------------------------------------------------------------------------------
/** Convert time_t to tm as UTC time.
* Portable implementation of gmtime_r (re-entrant gmtime) that works on Windows and Linux
Janik Zikovsky
committed
*
* @param clock pointer to time_t to convert
* @param result pointer to a struct tm (timeinfo structure) that will be filled.
* @return result if successful, or NULL if there was an error.
Janik Zikovsky
committed
*/
std::tm * gmtime_r_portable( const std::time_t *clock, struct std::tm *result )
{
#ifdef _WIN32
//Windows implementation
if (!gmtime_s(result, clock))
{ //Returns zero if successful
Janik Zikovsky
committed
return result;
}
else
{ //Returned some non-zero error code
Janik Zikovsky
committed
return NULL;
}
#else
//Unix implementation
return gmtime_r(clock, result);
#endif
}
//-----------------------------------------------------------------------------------------------
Janik Zikovsky
committed
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
/// utc_mktime() converts a struct tm that contains
/// broken down time in utc to a time_t. This function uses
/// a brute-force method of conversion that does not require
/// the environment variable TZ to be changed at all, and is
/// therefore slightly more thread-safe in that regard.
///
/// The difference between mktime() and utc_mktime() is that
/// standard mktime() expects the struct tm to be in localtime,
/// according to the current TZ and system setting, while utc_mktime()
/// always assumes that the struct tm is in UTC, and converts it
/// to time_t regardless of what TZ is currently set.
///
/// The difference between utc_mktime() and TzWrapper::iso_mktime()
/// is that iso_mktime() will parse straight from an ISO string,
/// and if the ISO timestamp ends in a 'Z', it will behave like
/// utc_mktime() except it will alter the TZ environment variable
/// to do it. If the ISO timestamp has no 'Z', then iso_mktime()
/// behaves like mktime().
///
/// Copyright (C) 2010, Chris Frey <cdfrey@foursquare.net>, To God be the glory
/// Released to the public domain.
time_t utc_mktime(struct tm *utctime)
{
time_t result;
struct tm tmp, check;
// loop, converting "local time" to time_t and back to utc tm,
// and adjusting until there are no differences... this
// automatically takes care of DST issues.
// do first conversion
tmp = *utctime;
tmp.tm_isdst = -1;
result = mktime(&tmp);
if( result == (time_t)-1 )
return (time_t)-1;
Janik Zikovsky
committed
if( gmtime_r_portable(&result, &check) == NULL )
Janik Zikovsky
committed
return (time_t)-1;
// loop until match
Janik Zikovsky
committed
int counter = 0;
while( counter < 15 &&
( check.tm_year != utctime->tm_year ||
Janik Zikovsky
committed
check.tm_mon != utctime->tm_mon ||
check.tm_mday != utctime->tm_mday ||
check.tm_hour != utctime->tm_hour ||
Janik Zikovsky
committed
check.tm_min != utctime->tm_min ) )
Janik Zikovsky
committed
{
tmp.tm_min += utctime->tm_min - check.tm_min;
tmp.tm_hour += utctime->tm_hour - check.tm_hour;
tmp.tm_mday += utctime->tm_mday - check.tm_mday;
tmp.tm_year += utctime->tm_year - check.tm_year;
tmp.tm_isdst = -1;
result = mktime(&tmp);
if( result == (time_t)-1 )
return (time_t)-1;
Janik Zikovsky
committed
gmtime_r_portable(&result, &check);
if( gmtime_r_portable(&result, &check) == NULL )
Janik Zikovsky
committed
return (time_t)-1;
Janik Zikovsky
committed
//Seems like there can be endless loops at the end of a month? E.g. sep 30, 2010 at 4:40 pm. This is to avoid it.
counter++;
Janik Zikovsky
committed
}
return result;
}
Janik Zikovsky
committed
} //namespace DateAndTimeHelpers
//------------------------------------------------------------------------------------------------
/** Default, empty constructor */
DateAndTime::DateAndTime() : _nanoseconds(0)
{}
//------------------------------------------------------------------------------------------------
/** Construct a date from nanoseconds.
* @param total_nanoseconds nanoseconds since Jan 1, 1990 (our epoch).
Janik Zikovsky
committed
*/
Gigg, Martyn Anthony
committed
DateAndTime::DateAndTime(const int64_t total_nanoseconds)
Janik Zikovsky
committed
{
Janik Zikovsky
committed
//Make sure that you cannot construct a date that is beyond the limits...
if (total_nanoseconds > MAX_NANOSECONDS)
_nanoseconds = MAX_NANOSECONDS;
else if (total_nanoseconds < MIN_NANOSECONDS)
_nanoseconds = MIN_NANOSECONDS;
else
_nanoseconds = total_nanoseconds;
Gigg, Martyn Anthony
committed
}
Janik Zikovsky
committed
//------------------------------------------------------------------------------------------------
/** Construct a time from an ISO8601 string
*
* @param ISO8601_string: and ISO8601 formatted string.
* "yyyy-mm-ddThh:mm:ss[Z+-]tz:tz"; although the T can be replaced by a space,
* and the time is optional, as is the time-zone specification.
*/
DateAndTime::DateAndTime(const std::string ISO8601_string) : _nanoseconds(0)
{
this->set_from_ISO8601_string(ISO8601_string);
}
//------------------------------------------------------------------------------------------------
/** Construct time from a boost::posix_time::ptime.
* @param _ptime boost::posix_time::ptime
*/
DateAndTime::DateAndTime(const boost::posix_time::ptime _ptime) : _nanoseconds(0)
{
this->set_from_ptime(_ptime);
Janik Zikovsky
committed
}
Janik Zikovsky
committed
//------------------------------------------------------------------------------------------------
/** Construct a time from the number of seconds and nanoseconds since Jan 1, 1990.
* @param seconds seconds since Jan 1, 1990.
* @param nanoseconds nanoseconds to add to the number of seconds
*/
DateAndTime::DateAndTime(const double seconds, const double nanoseconds)
{
double nano = seconds * 1e9 + nanoseconds;
//Limit times
if (nano > MAX_NANOSECONDS)
_nanoseconds = MAX_NANOSECONDS;
else if (nano < MIN_NANOSECONDS)
_nanoseconds = MIN_NANOSECONDS;
else
_nanoseconds = nano;
}
Gigg, Martyn Anthony
committed
//------------------------------------------------------------------------------------------------
Janik Zikovsky
committed
/** Construct a time from the number of seconds and nanoseconds since Jan 1, 1990.
* @param seconds seconds since Jan 1, 1990.
* @param nanoseconds nanoseconds to add to the number of seconds
*/
Gigg, Martyn Anthony
committed
DateAndTime::DateAndTime(const int64_t seconds, const int64_t nanoseconds)
Janik Zikovsky
committed
{
if (seconds >= MAX_SECONDS)
_nanoseconds = MAX_NANOSECONDS;
else if (seconds <= MIN_SECONDS)
_nanoseconds = MIN_NANOSECONDS;
else
_nanoseconds = seconds * 1e9 + nanoseconds;;
}
Gigg, Martyn Anthony
committed
//------------------------------------------------------------------------------------------------
Janik Zikovsky
committed
/** Construct a time from the number of seconds and nanoseconds since Jan 1, 1990.
* @param seconds seconds since Jan 1, 1990.
* @param nanoseconds nanoseconds to add to the number of seconds
*/
Gigg, Martyn Anthony
committed
DateAndTime::DateAndTime(const int32_t seconds, const int32_t nanoseconds)
Janik Zikovsky
committed
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
{
if (seconds >= MAX_SECONDS)
_nanoseconds = MAX_NANOSECONDS;
else if (seconds <= MIN_SECONDS)
_nanoseconds = MIN_NANOSECONDS;
else
_nanoseconds = seconds * 1e9 + nanoseconds;;
}
//===========================================================================================
//===========================================================================================
//------------------------------------------------------------------------------------------------
/** Get the time as a boost::posix_time::ptime.
* @return a boost::posix_time::ptime.
*/
boost::posix_time::ptime DateAndTime::to_ptime() const
{
return DateAndTimeHelpers::GPS_EPOCH + duration_from_nanoseconds(_nanoseconds);
}
//------------------------------------------------------------------------------------------------
/** Sets the date and time using a boost::posix_time::ptime
*
* @param _ptime boost::posix_time::ptime date and time.
*/
void DateAndTime::set_from_ptime(boost::posix_time::ptime _ptime)
{
if (_ptime.is_special())
{
// --- SPECIAL VALUES! ----
if (_ptime.is_infinity() || _ptime.is_pos_infinity())
_nanoseconds = MAX_NANOSECONDS;
if (_ptime.is_neg_infinity())
_nanoseconds = MIN_NANOSECONDS;
if (_ptime.is_not_a_date_time())
_nanoseconds = MIN_NANOSECONDS;
}
else
{
_nanoseconds = nanoseconds_from_duration(_ptime - DateAndTimeHelpers::GPS_EPOCH);
//Check for overflow
if (_nanoseconds < 0)
{
if (_ptime.date().year() >= 1990)
{
//nanoseconds is negative despite the year being higher than 1990
// ... means overflow occured
this->set_to_maximum();
}
}
else if (_nanoseconds > 0)
{
if (_ptime.date().year() < 1990)
{
//Nanoseconds is positive but the year is below 1990 = it should be negative!
this->set_to_minimum();
}
}
}
}
//===========================================================================================
//========================== time_t support =================================================
//===========================================================================================
//------------------------------------------------------------------------------------------------
/** Sets the date and time using a std::time_t
*
* @param _timet std::time_t to set to
*/
void DateAndTime::set_from_time_t(std::time_t _timet)
{
this->set_from_ptime( boost::posix_time::from_time_t( _timet ) );
}
//------------------------------------------------------------------------------------------------
/** Get the time as a std::time_t
* @return a std::time_t
*/
std::time_t DateAndTime::to_time_t() const
{
std::tm as_tm = boost::posix_time::to_tm(this->to_ptime());
std::time_t to_time_t = DateAndTimeHelpers::utc_mktime( &as_tm );
return to_time_t;
}
//-----------------------------------------------------------------------------------------------
Janik Zikovsky
committed
/** Convert a DateAndTime object to a std::tm time structure, using whatever time zone in the
* dateAndtime (should be UTC) .
*/
Janik Zikovsky
committed
std::tm DateAndTime::to_tm() const
{
Janik Zikovsky
committed
std::tm as_tm;
try
{
as_tm = boost::posix_time::to_tm(this->to_ptime());
} catch ( std::out_of_range & )
{ // MW 26/10 - above code throws on some setups, create "dummy" date object
as_tm.tm_year = 0;
as_tm.tm_mon = 0;
as_tm.tm_mday = 1;
as_tm.tm_hour = 0;
as_tm.tm_min = 0;
as_tm.tm_sec = 0;
as_tm.tm_wday = 0;
as_tm.tm_yday = 0;
as_tm.tm_isdst = 0;
}
return as_tm;
}
Janik Zikovsky
committed
Janik Zikovsky
committed
//-----------------------------------------------------------------------------------------------
/** Convert a DateAndTime object (in UTC) to a std::tm time structure, using the locat time zone.
*/
std::tm DateAndTime::to_localtime_tm() const
{
//Get the time_t in UTC
std::time_t my_time_t = this->to_time_t();
std::tm result;
Janik Zikovsky
committed
Janik Zikovsky
committed
#ifdef _WIN32
//Windows version
localtime_s(&result, &my_time_t);
Janik Zikovsky
committed
#else
Janik Zikovsky
committed
//Unix implementation
localtime_r(&my_time_t, &result);
Janik Zikovsky
committed
#endif
Janik Zikovsky
committed
return result;
}
Janik Zikovsky
committed
//-----------------------------------------------------------------------------------------------
Janik Zikovsky
committed
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
/** Convert a DateAndTime object (in UTC time) to std::time_t, in the LOCAL timezone.
*/
std::time_t DateAndTime::to_localtime_t() const
{
std::tm as_tm = this->to_tm();
std::time_t to_time_t = mktime( &as_tm );
return to_time_t;
}
//------------------------------------------------------------------------------------------------
/** Sets the date and time to the maximum allowed value */
void DateAndTime::set_to_maximum()
{
_nanoseconds = MAX_NANOSECONDS; //+2^62, or around the year 2136
}
/** Sets the date and time to the minimum allowed value */
void DateAndTime::set_to_minimum()
{
_nanoseconds = MIN_NANOSECONDS; //-2^62, or around the year 1843
}
/** Return the maximum time possible */
DateAndTime DateAndTime::maximum()
{
return DateAndTime(MAX_NANOSECONDS);
}
/** Return the minimum time possible */
DateAndTime DateAndTime::minimum()
{
return DateAndTime(MIN_NANOSECONDS);
}
/// A default date and time to use when time is not specified
const DateAndTime DateAndTime::defaultTime()
{
return DateAndTime("1970-01-01T00:00:00");
}
//------------------------------------------------------------------------------------------------
/** Sets the date and time using an ISO8601-formatted string
*
* @param str ISO8601 format string: "yyyy-mm-ddThh:mm:ss[Z+-]tz:tz"
*/
void DateAndTime::set_from_ISO8601_string(const std::string str)
Janik Zikovsky
committed
{
//Make a copy
std::string time = str;
Janik Zikovsky
committed
//Default of no timezone offset
bool positive_offset = true;
time_duration tz_offset = boost::posix_time::seconds(0);
Janik Zikovsky
committed
//Replace "T" with a space
size_t n = time.find('T');
if (n != std::string::npos)
Janik Zikovsky
committed
{
//Take out the T, for later
Janik Zikovsky
committed
time[n] = ' ';
Janik Zikovsky
committed
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
//Adjust for time zones. Fun!
//Look for the time zone marker
size_t n2;
n2 = time.find('Z', n);
if (n2 != std::string::npos)
{
//Found a Z. Remove it, and no timezone fix
time = time.substr(0, n2);
}
else
{
//Look for a + or - indicating time zone offset
size_t n_plus,n_minus,n5;
n_plus = time.find('+', n);
n_minus = time.find('-', n);
if ((n_plus != std::string::npos) || (n_minus != std::string::npos))
{
//Either a - or a + was found
if (n_plus != std::string::npos)
{
positive_offset = true;
n5 = n_plus;
}
else
{
positive_offset = false;
n5 = n_minus;
}
//Now, parse the offset time
std::string offset_str = time.substr(n5+1, time.size()-n5-1);
//Take out the offset from time string
time = time.substr(0, n5);
//Separate into minutes and hours
size_t n6;
std::string hours_str("0"), minutes_str("0");
n6 = offset_str.find(':');
if ((n6 != std::string::npos))
{
//Yes, minutes offset are specified
minutes_str = offset_str.substr(n6+1, offset_str.size()-n6-1);
hours_str = offset_str.substr(0, n6);
}
else
//Just hours
hours_str = offset_str;
//Convert to a time_duration
tz_offset = boost::posix_time::hours( boost::lexical_cast<long>(hours_str)) +
boost::posix_time::minutes( boost::lexical_cast<long>(minutes_str));
}
}
}
//The boost conversion will convert the string, then we subtract the time zone offset
if (positive_offset)
//The timezone is + so we need to subtract the hours
Janik Zikovsky
committed
this->set_from_ptime( boost::posix_time::time_from_string(time) - tz_offset );
Janik Zikovsky
committed
else
//The timezone is - so we need to ADD the hours
Janik Zikovsky
committed
this->set_from_ptime( boost::posix_time::time_from_string(time) + tz_offset );
}
Janik Zikovsky
committed
Janik Zikovsky
committed
//------------------------------------------------------------------------------------------------
/** Return the date and time as a simple string,
* for example, "19-Feb-2010 11:23:34.456000000"
*
*/
std::string DateAndTime::to_simple_string() const
{
return boost::posix_time::to_simple_string(this->to_ptime());
Janik Zikovsky
committed
}
Janik Zikovsky
committed
//------------------------------------------------------------------------------------------------
/** Return the date and time as a string, using formatting of strftime().
* Default format gives "1990-Jan-02 03:04:05"
*
* @format : format for strftime(). Default "%Y-%b-%d %H:%M:%S"
*/
std::string DateAndTime::to_string(const std::string format) const
Janik Zikovsky
committed
{
Janik Zikovsky
committed
char buffer [25];
std::tm date_as_tm = this->to_tm();
strftime (buffer, 25, format.c_str(), &date_as_tm);
return std::string(buffer);
Janik Zikovsky
committed
}
Janik Zikovsky
committed
//------------------------------------------------------------------------------------------------
/** Return the date and time as an ISO8601-formatted string without fractional seconds.
* @return string
*/
std::string DateAndTime::to_ISO8601_string() const
{
return this->to_string("%Y-%m-%dT%H:%M:%S");
}
Janik Zikovsky
committed
Janik Zikovsky
committed
////------------------------------------------------------------------------------------------------
Janik Zikovsky
committed
///** Stream operator
// */
//std::ostream& DateAndTime::operator<< (std::ostream& stream, const DateAndTime & obj)
Janik Zikovsky
committed
//{
// stream << obj->to_simple_string();
// return stream;
Janik Zikovsky
committed
//}
//------------------------------------------------------------------------------------------------
/** Get the year of this date.
* @return the year
Janik Zikovsky
committed
*/
Janik Zikovsky
committed
int DateAndTime::year() const
Janik Zikovsky
committed
{
Janik Zikovsky
committed
return to_ptime().date().year();
Janik Zikovsky
committed
}
Janik Zikovsky
committed
/** Get the month of this date.
* @return the month
Janik Zikovsky
committed
int DateAndTime::month() const
Janik Zikovsky
committed
return to_ptime().date().month();
}
Janik Zikovsky
committed
/** Get the day (of the month) of this date.
* @return the day
*/
int DateAndTime::day() const
{
return to_ptime().date().day();
}
Janik Zikovsky
committed
/** Get the hour (0-24) of this time.
* @return the hour
*/
int DateAndTime::hour() const
{
return to_ptime().time_of_day().hours();
Janik Zikovsky
committed
/** Get the minute (0-60) of this time.
* @return the minute
*/
int DateAndTime::minute() const
{
return to_ptime().time_of_day().minutes();
}
Janik Zikovsky
committed
/** Get the seconds (0-60) of this time.
* @return the second
Janik Zikovsky
committed
*/
Janik Zikovsky
committed
int DateAndTime::second() const
Janik Zikovsky
committed
{
Janik Zikovsky
committed
return to_ptime().time_of_day().seconds();
}
Janik Zikovsky
committed
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
/** Get the nanoseconds (remainder, < 1 second) of this time.
* @return the nanoseconds
*/
int DateAndTime::nanoseconds() const
{
return (_nanoseconds % 1000000000);
}
//------------------------------------------------------------------------------------------------
/** == operator
* @param rhs DateAndTime to compare
* @return true if equals
*/
bool DateAndTime::operator==(const DateAndTime& rhs) const
{
return _nanoseconds == rhs._nanoseconds;
}
/** == operator for boost::posix_time::ptime
* @param rhs boost::posix_time::ptime to compare
* @return true if equals
*/
bool DateAndTime::operator==(const boost::posix_time::ptime& rhs) const
{
return this->to_ptime() == rhs;
}
Janik Zikovsky
committed
/** != operator
* @param rhs DateAndTime to compare
* @return true if not equals
*/
bool DateAndTime::operator!=(const DateAndTime& rhs) const
{
return _nanoseconds != rhs._nanoseconds;
Janik Zikovsky
committed
}
Janik Zikovsky
committed
/** < operator
* @param rhs DateAndTime to compare
* @return true if less than
*/
bool DateAndTime::operator<(const DateAndTime& rhs) const
{
return _nanoseconds < rhs._nanoseconds;
}
Janik Zikovsky
committed
Janik Zikovsky
committed
/** <= operator
* @param rhs DateAndTime to compare
* @return true if less than or equals
Janik Zikovsky
committed
*/
Janik Zikovsky
committed
bool DateAndTime::operator<=(const DateAndTime& rhs) const
Janik Zikovsky
committed
{
Janik Zikovsky
committed
return _nanoseconds <= rhs._nanoseconds;
}
Janik Zikovsky
committed
Janik Zikovsky
committed
/** > operator
* @param rhs DateAndTime to compare
* @return true if greater than
*/
bool DateAndTime::operator>(const DateAndTime& rhs) const
{
return _nanoseconds > rhs._nanoseconds;
}
Janik Zikovsky
committed
Janik Zikovsky
committed
/** >= operator
* @param rhs DateAndTime to compare
* @return true if greater than or equals
*/
bool DateAndTime::operator>=(const DateAndTime& rhs) const
{
return _nanoseconds >= rhs._nanoseconds;
Janik Zikovsky
committed
}
Janik Zikovsky
committed
//------------------------------------------------------------------------------------------------
/** + operator to add time.
* @param nanosec number of nanoseconds to add
* @return modified DateAndTime.
*/
DateAndTime DateAndTime::operator+(const int64_t nanosec) const
Janik Zikovsky
committed
return DateAndTime(_nanoseconds + nanosec);
Janik Zikovsky
committed
/** += operator to add time.
* @param nanosec number of nanoseconds to add
* @return modified DateAndTime.
*/
DateAndTime& DateAndTime::operator+=(const int64_t nanosec)
Janik Zikovsky
committed
_nanoseconds += nanosec;
if (_nanoseconds > MAX_NANOSECONDS) _nanoseconds = MAX_NANOSECONDS;
else if (_nanoseconds < MIN_NANOSECONDS) _nanoseconds = MIN_NANOSECONDS;
return *this;
Janik Zikovsky
committed
/** - operator to subtract time.
* @param nanosec number of nanoseconds to subtract
* @return modified DateAndTime.
*/
DateAndTime DateAndTime::operator-(const int64_t nanosec) const
{
return DateAndTime(_nanoseconds - nanosec);
}
Janik Zikovsky
committed
Janik Zikovsky
committed
/** -= operator to subtract time.
* @param nanosec number of nanoseconds to subtract
* @return modified DateAndTime.
Janik Zikovsky
committed
*/
Janik Zikovsky
committed
DateAndTime& DateAndTime::operator-=(const int64_t nanosec)
Janik Zikovsky
committed
{
Janik Zikovsky
committed
_nanoseconds -= nanosec;
if (_nanoseconds > MAX_NANOSECONDS) _nanoseconds = MAX_NANOSECONDS;
else if (_nanoseconds < MIN_NANOSECONDS) _nanoseconds = MIN_NANOSECONDS;
return *this;
Janik Zikovsky
committed
}
Janik Zikovsky
committed
Janik Zikovsky
committed
//------------------------------------------------------------------------------------------------
/** + operator to add time.
* @param td time_duration to add
* @return modified DateAndTime.
Janik Zikovsky
committed
*/
Janik Zikovsky
committed
DateAndTime DateAndTime::operator+(const time_duration& td) const
Janik Zikovsky
committed
{
Janik Zikovsky
committed
return this->operator +(nanoseconds_from_duration(td));
Janik Zikovsky
committed
}
Janik Zikovsky
committed
/** += operator to add time.
* @param td time_duration to add
* @return modified DateAndTime.
*/
DateAndTime& DateAndTime::operator+=(const time_duration& td)
{
return this->operator +=(nanoseconds_from_duration(td));
}
Janik Zikovsky
committed
Janik Zikovsky
committed
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
/** - operator to subtract time.
* @param td time_duration to subtract
* @return modified DateAndTime.
*/
DateAndTime DateAndTime::operator-(const time_duration& td) const
{
return this->operator -(nanoseconds_from_duration(td));
}
/** -= operator to subtract time.
* @param td time_duration to subtract
* @return modified DateAndTime.
*/
DateAndTime& DateAndTime::operator-=(const time_duration& td)
{
return this->operator -=(nanoseconds_from_duration(td));
}
//------------------------------------------------------------------------------------------------
/** + operator to add time.
* @param sec duration to add
* @return modified DateAndTime.
*/
DateAndTime DateAndTime::operator+(const double sec) const
{
return this->operator +(nanoseconds_from_seconds(sec));
}
/** += operator to add time.
* @param sec duration to add
* @return modified DateAndTime.
Janik Zikovsky
committed
*/
Janik Zikovsky
committed
DateAndTime& DateAndTime::operator+=(const double sec)
Janik Zikovsky
committed
{
Janik Zikovsky
committed
return this->operator +=(nanoseconds_from_seconds(sec));
Janik Zikovsky
committed
}
Janik Zikovsky
committed
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
/** - operator to subtract time.
* @param sec duration to subtract
* @return modified DateAndTime.
*/
DateAndTime DateAndTime::operator-(const double sec) const
{
return this->operator -(nanoseconds_from_seconds(sec));
}
/** -= operator to subtract time.
* @param sec duration to subtract
* @return modified DateAndTime.
*/
DateAndTime& DateAndTime::operator-=(const double sec)
{
return this->operator -=(nanoseconds_from_seconds(sec));
}
//------------------------------------------------------------------------------------------------
/** Subtract two times.
* @return a time_duration
*/
time_duration DateAndTime::operator-(const DateAndTime& rhs) const
{
return this->to_ptime() - rhs.to_ptime();
}
//------------------------------------------------------------------------------------------------
/** Returns the current DateAndTime, in UTC time, with microsecond precision
* @return the current time.
*/
DateAndTime DateAndTime::get_current_time()
{
return DateAndTime(boost::posix_time::microsec_clock::universal_time());
}
Janik Zikovsky
committed
//-----------------------------------------------------------------------------------------------
Janik Zikovsky
committed
/**
* Return the number of seconds in a time_duration, as a double, including fractional seconds.
Janik Zikovsky
committed
*/
Janik Zikovsky
committed
double DateAndTime::seconds_from_duration(time_duration duration)
Janik Zikovsky
committed
{
Janik Zikovsky
committed
#ifdef BOOST_DATE_TIME_HAS_NANOSECONDS
// Nanosecond resolution
return static_cast<double>(duration.total_nanoseconds()) / 1e9;
#else
// Microsecond resolution
return static_cast<double>(duration.total_microseconds()) / 1e6;
#endif
Janik Zikovsky
committed
}
Janik Zikovsky
committed
//-----------------------------------------------------------------------------------------------
Janik Zikovsky
committed
/**
* Return a time_duration object with the given the number of seconds
Janik Zikovsky
committed
*/
Janik Zikovsky
committed
time_duration DateAndTime::duration_from_seconds(double duration)
Janik Zikovsky
committed
{
Janik Zikovsky
committed
long secs = static_cast<long>( duration );
//Limit the seconds to the range of long (avoid overflows)
if (duration >= std::numeric_limits<int>::max())
return boost::posix_time::time_duration( boost::posix_time::max_date_time );
else if (duration <= std::numeric_limits<int>::min())
return boost::posix_time::time_duration( boost::posix_time::min_date_time );
#ifdef BOOST_DATE_TIME_HAS_NANOSECONDS
// Nanosecond resolution
long fracsecs = long ( 1e9 * fmod(duration, 1.0) );
return boost::posix_time::time_duration(0,0,secs, fracsecs);
#else
// Microsecond resolution
long fracsecs = long ( 1e6 * fmod(duration, 1.0) );
return boost::posix_time::time_duration(0,0,secs, fracsecs);
#endif
Janik Zikovsky
committed
}
Janik Zikovsky
committed
//-----------------------------------------------------------------------------------------------
Janik Zikovsky
committed
/** time duration in nanoseconds. Duration is limited to
* MAX_NANOSECONDS and MIN_NANOSECONDS to avoid overflows.
* @param td time_duration instance.
* @Return an int64 of the number of nanoseconds
Janik Zikovsky
committed
*/
Janik Zikovsky
committed
int64_t DateAndTime::nanoseconds_from_duration(const time_duration & td)
Janik Zikovsky
committed
{
Janik Zikovsky
committed
int64_t nano;
#ifdef BOOST_DATE_TIME_HAS_NANOSECONDS
// Nanosecond resolution
nano = td.total_nanoseconds();
#else
// Microsecond resolution
nano = (td.total_microseconds()*1000);
#endif
//Use these limits to avoid integer overflows
if (nano >MAX_NANOSECONDS)
return MAX_NANOSECONDS;
else if (nano < MIN_NANOSECONDS)
return MIN_NANOSECONDS;
else
return nano;
Janik Zikovsky
committed
}
Janik Zikovsky
committed
//-----------------------------------------------------------------------------------------------
Janik Zikovsky
committed
/** time duration from nanoseconds
* @param dur duration in nanoseconds, as an int
* @return a time_duration type
*/
Janik Zikovsky
committed
time_duration DateAndTime::duration_from_nanoseconds(int64_t dur)
{
Janik Zikovsky
committed
#ifdef BOOST_DATE_TIME_HAS_NANOSECONDS
// Nanosecond resolution
return boost::posix_time::time_duration(0,0,0,dur);
#else
// Microsecond resolution
return boost::posix_time::time_duration(0,0,0,dur/1000);
#endif
}
Michael Whitty
committed
Janik Zikovsky
committed
//-----------------------------------------------------------------------------------------------
/** Nanoseconds from seconds, with limits
* @param dur duration in seconds, as a double
* @return int64 of the number of nanoseconds
*/
int64_t DateAndTime::nanoseconds_from_seconds(double sec)
{
double nano = sec * 1e9;
//Use these limits to avoid integer overflows
if (nano >MAX_NANOSECONDS)
return MAX_NANOSECONDS;
else if (nano < MIN_NANOSECONDS)
return MIN_NANOSECONDS;
else
return int64_t(nano);
}
//-----------------------------------------------------------------------------------------------
/** Static method to create a vector of DateAndTime objects
* using a start time and seconds offset. To speed things up,
* no limit checking is performed!
*
* @param start :: DateAndTime at 0.
* @param seconds :: a vector of doubles of the number of seconds.
* @param out :: reference to a vector that will be filled with DateAndTime's
*/
void DateAndTime::createVector(const DateAndTime start, const std::vector<double> & seconds, std::vector<DateAndTime> & out)
{
int64_t startnano = start._nanoseconds;
size_t num = seconds.size();
out.resize(num);
std::vector<double>::const_iterator it;
size_t i = 0;
for(it = seconds.begin(); it != seconds.end(); it++)
{
out[i]._nanoseconds = startnano + static_cast<int64_t>( (*it) * 1000000000.0 );
Janik Zikovsky
committed
Janik Zikovsky
committed
Janik Zikovsky
committed
TimeInterval::TimeInterval(const DateAndTime& from, const DateAndTime& to)
:m_begin(from)
{
if (to > from) m_end = to;
else
m_end = from;
}
/** Returns an intersection of this interval with \a ti
Janik Zikovsky
committed
@param ti Time interval
@return A valid time interval if this interval intersects with \a ti or
an empty interval otherwise.
*/
TimeInterval TimeInterval::intersection(const TimeInterval& ti)const
{
if (!isValid() || !ti.isValid()) return TimeInterval();
Janik Zikovsky
committed
DateAndTime t1 = begin();
if (ti.begin() > t1) t1 = ti.begin();
Janik Zikovsky
committed
DateAndTime t2 = end();
if (ti.end() < t2) t2 = ti.end();
return t1 < t2? TimeInterval(t1,t2) : TimeInterval();
}
/// String representation of the begin time
std::string TimeInterval::begin_str()const
{
Janik Zikovsky
committed
return boost::posix_time::to_simple_string(this->m_begin.to_ptime());
}
/// String representation of the end time
std::string TimeInterval::end_str()const
{
Janik Zikovsky
committed
return boost::posix_time::to_simple_string(this->m_end.to_ptime());
Janik Zikovsky
committed