Search code examples
c++jsonc++11c++-chronocpprest-sdk

What type to use when accessing and storing/parsing std::chrono::duration::milliseconds (cpprest)


A simplified example:

//...

std::chrono::milliseconds _delay; //field in question

unsigned long getDelay() const
{
    return _delay.count();
}

void setDelay(unsigned long delay)
{
    _delay = std::chrono::milliseconds(delay);
}

json::value toJson() const
{
    using namespace web;
    json::value obj;
    obj[delay] = json::value::number(_delay.count());

    return obj;
}

bool fromJson(web::json::value value)
{
    for (auto it = value.as_object().cbegin(); it != value.as_object().cend(); ++it)
    {
        const std::string& str = it->first;
        const json::value& v = it->second;

        if (str == "delay")
        {
            if (v.is_integer())
            {
                _id = v.as_number().to_uint64(); //was v.as_integer(); - thx Nicol Bogas
                continue;
            }
            else
            {
                return false;
            }
        }

        //...
    }
}

My class contains a bunch of std::chrono::milliseconds fields which represent corresponding delays. I want to store these values in a JSON representation of the class. Most JSON values only operate with standard internal types, but std::chrono::milliseconds implements std::chrono::duration template. It has a count() method that returns an amount of ticks as a variable of rep type which on my system is a typedef to long long

The code is required to be portable. How safe is it, from a practical view, to convert the result of count() to simple long and that pass it to JSON library? Have I implemented accessors correctly (with unsigned long type)? In practice, I usually store delay values in a range from 0 to 5000, but nothing stops other people from editing configuration files and writing incorrect values there, which might cause runtime errors and strange behavior.

P.S. Just to be clear - it's not a Rubber Duck Debugging thread. I've never dealt with "might be very big" values before and C++ with multiple libstdc++ implementations and typedefs makes it difficult. I am worried about potential bugs and pitfalls. Thanks.


Solution

  • I would suggest defining your own duration type "double precision seconds". This can then be extracted as the count, and passed to other languages with a clear and unambiguous meaning. Some sample code (nothing to do with json):

     TimePoint nowTime(std::chrono::system_clock::now());
     typedef std::chrono::duration<double>       FSeconds;
     FSeconds delta = std::chrono::duration_cast<FSeconds>(nowTime - startTime);
     ofs << "@" << std::fixed << delta.count() //...
    

    So here, delta.count is seconds, but it is real rather than integer, so the miliseconds, or whatever, are preserved in the decimal.