added parseTimeDuration() function, to replace boost::posix_time::
duration_from_string(), which is badly broken
This commit is contained in:
parent
299345f8f6
commit
9fb1cf5a54
4 changed files with 257 additions and 7 deletions
|
@ -22,7 +22,7 @@
|
||||||
|
|
||||||
|
|
||||||
Author : $Author: fgerlits $
|
Author : $Author: fgerlits $
|
||||||
Version : $Revision: 1.9 $
|
Version : $Revision: 1.10 $
|
||||||
Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/core/include/LiveSupport/Core/TimeConversion.h,v $
|
Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/core/include/LiveSupport/Core/TimeConversion.h,v $
|
||||||
|
|
||||||
------------------------------------------------------------------------------*/
|
------------------------------------------------------------------------------*/
|
||||||
|
@ -71,15 +71,57 @@ using namespace LiveSupport;
|
||||||
* A helper object holding static time conversion functions.
|
* A helper object holding static time conversion functions.
|
||||||
*
|
*
|
||||||
* @author $Author: fgerlits $
|
* @author $Author: fgerlits $
|
||||||
* @version $Revision: 1.9 $
|
* @version $Revision: 1.10 $
|
||||||
*/
|
*/
|
||||||
class TimeConversion
|
class TimeConversion
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
/**
|
||||||
|
* Parse a time string.
|
||||||
|
*
|
||||||
|
* It cuts off the portion between the end of the string and the last
|
||||||
|
* occurrence of the separator character. For example, if called with
|
||||||
|
* the parameters "00:01:02" and ':', the function returns "02" and
|
||||||
|
* truncates the original string to "00:01".
|
||||||
|
*
|
||||||
|
* If the separator character is not found in <code>timeString</code>,
|
||||||
|
* a copy of the whole <code>timeString</code> is returned, and the
|
||||||
|
* original <code>timeString</code> is changed to the empty string.
|
||||||
|
*
|
||||||
|
* @param timeString the input argument; on return, the rest of the
|
||||||
|
* string, after the return value cut off
|
||||||
|
* @param separator a separator character, usually ':'
|
||||||
|
* @return the part of the string which was cut off
|
||||||
|
*/
|
||||||
|
static Ptr<std::string>::Ref
|
||||||
|
nextNumberFromEnd(Ptr<std::string>::Ref timeString,
|
||||||
|
char separator) throw ();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse a decimal string.
|
||||||
|
*
|
||||||
|
* It cuts off the portion between the end of the string and the last
|
||||||
|
* occurrence of the separator character. For example, if called with
|
||||||
|
* the parameters "1.23" and '.', the function returns "23" and
|
||||||
|
* truncates the original string to "1".
|
||||||
|
*
|
||||||
|
* If the separator character is not found in <code>timeString</code>,
|
||||||
|
* then an empty string is returned, and the
|
||||||
|
* original <code>timeString</code> remains unchanged.
|
||||||
|
*
|
||||||
|
* @param decimalString the input argument; on return, the rest of
|
||||||
|
* the string, after the return value cut off
|
||||||
|
* @param separator a separator character, usually '.'
|
||||||
|
* @return the part of the string which was cut off
|
||||||
|
*/
|
||||||
|
static Ptr<std::string>::Ref
|
||||||
|
nextNumberFromStart(Ptr<std::string>::Ref decimalString,
|
||||||
|
char separator) throw ();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The default constructor.
|
* The default constructor.
|
||||||
*/
|
*/
|
||||||
TimeConversion(void) throw ()
|
TimeConversion(void) throw ()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,10 +199,38 @@ class TimeConversion
|
||||||
* more than two characters wide, e.g.: "8765:48:45".
|
* more than two characters wide, e.g.: "8765:48:45".
|
||||||
*
|
*
|
||||||
* @param duration the time duration to convert.
|
* @param duration the time duration to convert.
|
||||||
|
* @return the time duration in string format
|
||||||
*/
|
*/
|
||||||
static Ptr<std::string>::Ref
|
static Ptr<std::string>::Ref
|
||||||
timeDurationToHhMmSsString(Ptr<time_duration>::Ref duration)
|
timeDurationToHhMmSsString(Ptr<time_duration>::Ref duration)
|
||||||
throw ();
|
throw ();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse a string to a time_duration.
|
||||||
|
* Similar to boost::posix_time::duration_from_string(), only
|
||||||
|
* not broken quite as badly.
|
||||||
|
*
|
||||||
|
* Parsing is right-to-left, starting with seconds: for example,
|
||||||
|
* 5 means 5 seconds; 01:02.03 means 1m 2.03s; 1:2:3 means 1h 2m 3s.
|
||||||
|
*
|
||||||
|
* If the time format is invalid, no exception is thrown, but the
|
||||||
|
* result is undefined (usually 00:00:00).
|
||||||
|
* TODO: fix this, by adding a format check
|
||||||
|
*
|
||||||
|
* @param durationString the duration as string
|
||||||
|
* @return the duration as a time_duration
|
||||||
|
*/
|
||||||
|
static Ptr<time_duration>::Ref
|
||||||
|
parseTimeDuration(Ptr<std::string>::Ref durationString)
|
||||||
|
throw ();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the number of digits used for fractional seconds
|
||||||
|
* in time durations.
|
||||||
|
* Returns the constant 6, for microsecond precision.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
getNumberOfDigitsPrecision(void) throw ();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
|
|
||||||
|
|
||||||
Author : $Author: fgerlits $
|
Author : $Author: fgerlits $
|
||||||
Version : $Revision: 1.9 $
|
Version : $Revision: 1.10 $
|
||||||
Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/core/src/TimeConversion.cxx,v $
|
Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/core/src/TimeConversion.cxx,v $
|
||||||
|
|
||||||
------------------------------------------------------------------------------*/
|
------------------------------------------------------------------------------*/
|
||||||
|
@ -33,6 +33,8 @@
|
||||||
#include "configure.h"
|
#include "configure.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <iomanip>
|
||||||
|
|
||||||
#include "LiveSupport/Core/TimeConversion.h"
|
#include "LiveSupport/Core/TimeConversion.h"
|
||||||
|
|
||||||
|
|
||||||
|
@ -46,6 +48,10 @@ using namespace LiveSupport::Core;
|
||||||
|
|
||||||
/* ================================================ local constants & macros */
|
/* ================================================ local constants & macros */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The number of digits used for fractional seconds in time durations.
|
||||||
|
*/
|
||||||
|
static const int numberOfDigitsPrecision = 6;
|
||||||
|
|
||||||
/* =============================================== local function prototypes */
|
/* =============================================== local function prototypes */
|
||||||
|
|
||||||
|
@ -207,3 +213,116 @@ TimeConversion :: timeDurationToHhMmSsString(
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------
|
||||||
|
* Parse a string to a time_duration.
|
||||||
|
*----------------------------------------------------------------------------*/
|
||||||
|
Ptr<time_duration>::Ref
|
||||||
|
TimeConversion :: parseTimeDuration(Ptr<std::string>::Ref durationString)
|
||||||
|
throw ()
|
||||||
|
{
|
||||||
|
int micros = 0;
|
||||||
|
int seconds = 0;
|
||||||
|
int minutes = 0;
|
||||||
|
int hours = 0;
|
||||||
|
|
||||||
|
Ptr<std::string>::Ref temp(new std::string(*durationString));
|
||||||
|
|
||||||
|
if (temp->length() > 0) {
|
||||||
|
Ptr<std::string>::Ref secondsString = nextNumberFromEnd(temp, ':');
|
||||||
|
Ptr<std::string>::Ref fractionsString = nextNumberFromStart(
|
||||||
|
secondsString, '.');
|
||||||
|
if (fractionsString->length() > 0) {
|
||||||
|
std::stringstream fractionsStream;
|
||||||
|
fractionsStream << std::left
|
||||||
|
<< std::setw(
|
||||||
|
TimeConversion::getNumberOfDigitsPrecision() )
|
||||||
|
<< std::setfill('0')
|
||||||
|
<< *fractionsString;
|
||||||
|
fractionsStream >> micros;
|
||||||
|
}
|
||||||
|
if (secondsString->length() > 0) {
|
||||||
|
std::stringstream secondsStream(*secondsString);
|
||||||
|
secondsStream >> seconds;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (temp->length() > 0) {
|
||||||
|
Ptr<std::string>::Ref minutesString = nextNumberFromEnd(temp, ':');
|
||||||
|
std::stringstream minutesStream(*minutesString);
|
||||||
|
minutesStream >> minutes;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (temp->length() > 0) {
|
||||||
|
std::stringstream hoursStream(*temp);
|
||||||
|
hoursStream >> hours;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ptr<time_duration>::Ref result(new time_duration(
|
||||||
|
hours, minutes, seconds, micros ));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------
|
||||||
|
* Parse a time string.
|
||||||
|
*----------------------------------------------------------------------------*/
|
||||||
|
Ptr<std::string>::Ref
|
||||||
|
TimeConversion :: nextNumberFromEnd(Ptr<std::string>::Ref timeString,
|
||||||
|
char separator)
|
||||||
|
throw ()
|
||||||
|
{
|
||||||
|
Ptr<std::string>::Ref result;
|
||||||
|
unsigned int pos = timeString->find_last_of(separator);
|
||||||
|
|
||||||
|
if (pos != std::string::npos) {
|
||||||
|
if (pos != timeString->length()-1) {
|
||||||
|
result.reset(new std::string(*timeString, pos+1));
|
||||||
|
} else {
|
||||||
|
result.reset(new std::string);
|
||||||
|
}
|
||||||
|
*timeString = timeString->substr(0, pos);
|
||||||
|
} else {
|
||||||
|
result.reset(new std::string(*timeString));
|
||||||
|
*timeString = std::string("");
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------
|
||||||
|
* Parse a decimal string.
|
||||||
|
*----------------------------------------------------------------------------*/
|
||||||
|
Ptr<std::string>::Ref
|
||||||
|
TimeConversion :: nextNumberFromStart(Ptr<std::string>::Ref timeString,
|
||||||
|
char separator)
|
||||||
|
throw ()
|
||||||
|
{
|
||||||
|
Ptr<std::string>::Ref result;
|
||||||
|
unsigned int pos = timeString->find(separator);
|
||||||
|
|
||||||
|
if (pos != std::string::npos) {
|
||||||
|
if (pos != timeString->length()-1) {
|
||||||
|
result.reset(new std::string(*timeString, pos+1));
|
||||||
|
} else {
|
||||||
|
result.reset(new std::string);
|
||||||
|
}
|
||||||
|
*timeString = timeString->substr(0, pos);
|
||||||
|
} else {
|
||||||
|
result.reset(new std::string(""));
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------
|
||||||
|
* Get the number of digits used for fractional seconds in time durations.
|
||||||
|
*----------------------------------------------------------------------------*/
|
||||||
|
int
|
||||||
|
TimeConversion :: getNumberOfDigitsPrecision(void) throw ()
|
||||||
|
{
|
||||||
|
return numberOfDigitsPrecision;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
|
|
||||||
|
|
||||||
Author : $Author: fgerlits $
|
Author : $Author: fgerlits $
|
||||||
Version : $Revision: 1.8 $
|
Version : $Revision: 1.9 $
|
||||||
Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/core/src/TimeConversionTest.cxx,v $
|
Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/core/src/TimeConversionTest.cxx,v $
|
||||||
|
|
||||||
------------------------------------------------------------------------------*/
|
------------------------------------------------------------------------------*/
|
||||||
|
@ -239,3 +239,55 @@ TimeConversionTest :: durationToStringTest(void)
|
||||||
CPPUNIT_ASSERT_EQUAL(std::string("111:22:33"), *hhMmSsString);
|
CPPUNIT_ASSERT_EQUAL(std::string("111:22:33"), *hhMmSsString);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------------
|
||||||
|
* Test the parseTimeDuration() function.
|
||||||
|
*----------------------------------------------------------------------------*/
|
||||||
|
void
|
||||||
|
TimeConversionTest :: parseTimeDurationTest(void)
|
||||||
|
throw (CPPUNIT_NS::Exception)
|
||||||
|
{
|
||||||
|
// legal arguments
|
||||||
|
Ptr<std::string>::Ref timeString(new std::string("01:02:03.503700"));
|
||||||
|
Ptr<time_duration>::Ref duration;
|
||||||
|
CPPUNIT_ASSERT_NO_THROW(
|
||||||
|
duration = TimeConversion::parseTimeDuration(timeString)
|
||||||
|
);
|
||||||
|
CPPUNIT_ASSERT(duration);
|
||||||
|
CPPUNIT_ASSERT_EQUAL(std::string("01:02:03.503700"),
|
||||||
|
to_simple_string(*duration));
|
||||||
|
|
||||||
|
timeString.reset(new std::string("02:03.5"));
|
||||||
|
CPPUNIT_ASSERT_NO_THROW(
|
||||||
|
duration = TimeConversion::parseTimeDuration(timeString)
|
||||||
|
);
|
||||||
|
CPPUNIT_ASSERT(duration);
|
||||||
|
CPPUNIT_ASSERT_EQUAL(std::string("00:02:03.500000"),
|
||||||
|
to_simple_string(*duration));
|
||||||
|
|
||||||
|
timeString.reset(new std::string("77"));
|
||||||
|
CPPUNIT_ASSERT_NO_THROW(
|
||||||
|
duration = TimeConversion::parseTimeDuration(timeString)
|
||||||
|
);
|
||||||
|
CPPUNIT_ASSERT(duration);
|
||||||
|
CPPUNIT_ASSERT_EQUAL(std::string("00:01:17"),
|
||||||
|
to_simple_string(*duration));
|
||||||
|
|
||||||
|
// illegal arguments
|
||||||
|
timeString.reset(new std::string("5 minutes and 2 seconds"));
|
||||||
|
CPPUNIT_ASSERT_NO_THROW(
|
||||||
|
duration = TimeConversion::parseTimeDuration(timeString)
|
||||||
|
);
|
||||||
|
CPPUNIT_ASSERT(duration);
|
||||||
|
CPPUNIT_ASSERT_EQUAL(std::string("00:00:05"), // bad!
|
||||||
|
to_simple_string(*duration));
|
||||||
|
|
||||||
|
timeString.reset(new std::string("1.2.3"));
|
||||||
|
CPPUNIT_ASSERT_NO_THROW(
|
||||||
|
duration = TimeConversion::parseTimeDuration(timeString)
|
||||||
|
);
|
||||||
|
CPPUNIT_ASSERT(duration);
|
||||||
|
CPPUNIT_ASSERT_EQUAL(std::string("00:00:01.000002"), // bad!
|
||||||
|
to_simple_string(*duration));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
|
|
||||||
|
|
||||||
Author : $Author: fgerlits $
|
Author : $Author: fgerlits $
|
||||||
Version : $Revision: 1.7 $
|
Version : $Revision: 1.8 $
|
||||||
Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/core/src/TimeConversionTest.h,v $
|
Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/core/src/TimeConversionTest.h,v $
|
||||||
|
|
||||||
------------------------------------------------------------------------------*/
|
------------------------------------------------------------------------------*/
|
||||||
|
@ -58,7 +58,7 @@ namespace Core {
|
||||||
* Unit test for the TimeConversion class.
|
* Unit test for the TimeConversion class.
|
||||||
*
|
*
|
||||||
* @author $Author: fgerlits $
|
* @author $Author: fgerlits $
|
||||||
* @version $Revision: 1.7 $
|
* @version $Revision: 1.8 $
|
||||||
* @see TimeConversion
|
* @see TimeConversion
|
||||||
*/
|
*/
|
||||||
class TimeConversionTest : public CPPUNIT_NS::TestFixture
|
class TimeConversionTest : public CPPUNIT_NS::TestFixture
|
||||||
|
@ -70,6 +70,7 @@ class TimeConversionTest : public CPPUNIT_NS::TestFixture
|
||||||
CPPUNIT_TEST(nowTest);
|
CPPUNIT_TEST(nowTest);
|
||||||
CPPUNIT_TEST(sleepTest);
|
CPPUNIT_TEST(sleepTest);
|
||||||
CPPUNIT_TEST(durationToStringTest);
|
CPPUNIT_TEST(durationToStringTest);
|
||||||
|
CPPUNIT_TEST(parseTimeDurationTest);
|
||||||
CPPUNIT_TEST_SUITE_END();
|
CPPUNIT_TEST_SUITE_END();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -123,6 +124,14 @@ class TimeConversionTest : public CPPUNIT_NS::TestFixture
|
||||||
void
|
void
|
||||||
durationToStringTest(void) throw (CPPUNIT_NS::Exception);
|
durationToStringTest(void) throw (CPPUNIT_NS::Exception);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test the parseTimeDuration() function.
|
||||||
|
*
|
||||||
|
* @exception CPPUNIT_NS::Exception on test failures.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
parseTimeDurationTest(void) throw (CPPUNIT_NS::Exception);
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue