added parseTimeDuration() function, to replace boost::posix_time::

duration_from_string(), which is badly broken
This commit is contained in:
fgerlits 2005-07-26 10:36:01 +00:00
parent 299345f8f6
commit 9fb1cf5a54
4 changed files with 257 additions and 7 deletions

View file

@ -22,7 +22,7 @@
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 $
------------------------------------------------------------------------------*/
@ -71,15 +71,57 @@ using namespace LiveSupport;
* A helper object holding static time conversion functions.
*
* @author $Author: fgerlits $
* @version $Revision: 1.9 $
* @version $Revision: 1.10 $
*/
class TimeConversion
{
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.
*/
TimeConversion(void) throw ()
TimeConversion(void) throw ()
{
}
@ -157,10 +199,38 @@ class TimeConversion
* more than two characters wide, e.g.: "8765:48:45".
*
* @param duration the time duration to convert.
* @return the time duration in string format
*/
static Ptr<std::string>::Ref
timeDurationToHhMmSsString(Ptr<time_duration>::Ref duration)
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 ();
};

View file

@ -22,7 +22,7 @@
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 $
------------------------------------------------------------------------------*/
@ -33,6 +33,8 @@
#include "configure.h"
#endif
#include <iomanip>
#include "LiveSupport/Core/TimeConversion.h"
@ -46,6 +48,10 @@ using namespace LiveSupport::Core;
/* ================================================ local constants & macros */
/**
* The number of digits used for fractional seconds in time durations.
*/
static const int numberOfDigitsPrecision = 6;
/* =============================================== local function prototypes */
@ -207,3 +213,116 @@ TimeConversion :: timeDurationToHhMmSsString(
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;
}

View file

@ -22,7 +22,7 @@
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 $
------------------------------------------------------------------------------*/
@ -239,3 +239,55 @@ TimeConversionTest :: durationToStringTest(void)
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));
}

View file

@ -22,7 +22,7 @@
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 $
------------------------------------------------------------------------------*/
@ -58,7 +58,7 @@ namespace Core {
* Unit test for the TimeConversion class.
*
* @author $Author: fgerlits $
* @version $Revision: 1.7 $
* @version $Revision: 1.8 $
* @see TimeConversion
*/
class TimeConversionTest : public CPPUNIT_NS::TestFixture
@ -70,6 +70,7 @@ class TimeConversionTest : public CPPUNIT_NS::TestFixture
CPPUNIT_TEST(nowTest);
CPPUNIT_TEST(sleepTest);
CPPUNIT_TEST(durationToStringTest);
CPPUNIT_TEST(parseTimeDurationTest);
CPPUNIT_TEST_SUITE_END();
protected:
@ -123,6 +124,14 @@ class TimeConversionTest : public CPPUNIT_NS::TestFixture
void
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: