radman
radman

Reputation: 18555

converting a timestring to a duration

At the moment I am trying to read in a timestring formatted and create a duration from that. I am currently trying to use the boost date_time time_duration class to read and store the value.

boost date_time provides a method time_duration duration_from_string(std::string) that allows a time_duration to be created from a time string and it accepts strings formatted appropriately ("[-]h[h][:mm][:ss][.fff]".).

Now this method works fine if you use a correctly formatted time string. However if you submit something invalid like "ham_sandwich" or "100" then you will instead be returned a time_duration that is not valid. Specifically if you try to pass it to a standard output stream then an assertion will occur.

My question is: Does anyone know how to test the validity of the boost time_duration? and failing that can you suggest another method of reading a timestring and getting a duration from it?

Note: I have tried the obvious testing methods that time_duration provides; is_not_a_date_time(), is_special() etc and they don't pick up that there is an issue.

Using boost 1.38.0

Upvotes: 1

Views: 1928

Answers (2)

Sam Hartsfield
Sam Hartsfield

Reputation: 1451

From the documentation, it looks like you may want to try using the stream operators (operator<<, operator>>); error conditions are described at Date Time Input/Output.

Alternately, I suppose you could validate the string before passing it in. Right offhand, it doesn't look like that particular method has any error handling.

Edit: I'm not sure I would have thought to check the return value like this if it weren't for Brian's answer, but for completeness here's a full example that takes a string as input. You can either check the return value or have it throw an exception (I believe you'd want to catch std::ios_base_failure):

#include <iostream>
#include <sstream>
#include <string>
#include <boost/date_time/posix_time/posix_time.hpp>

using namespace std;
using namespace boost::posix_time;

int main(int argc, char **argv) {
    if (argc < 2) {
        cout << "Usage: " << argv[0] << " TIME_DURATION" << endl;
        return 2;
    }

    // No exception
    stringstream ss_noexcept(argv[1]);
    time_duration td1;
    if (ss_noexcept >> td1) {
        cout << "Valid time duration: " << td1 << endl;
    } else {
        cout << "Invalid time duration." << endl;
    }

    // Throws exception
    stringstream ss2;
    time_duration td2;
    ss2.exceptions(ios_base::failbit);
    ss2.str(argv[1]);
    try {
        ss2 >> td2;
        cout << "Time duration: " << td2 << endl;
    } catch (ios_base::failure e) {
        cout << "Invalid time duration (exception caught). what():\n"
                << e.what() << endl;
    }
}

Upvotes: 5

Brian Neal
Brian Neal

Reputation: 32389

Use the stream operators.

time_duration td;
if (std::cin >> td)
{
   // it's valid
}
else
{
   // it isn't valid
}

Upvotes: 2

Related Questions