How to convert nanoseconds to ptime in boost C++

219 Views Asked by At

Say I have a nanoseconds, 1614601874317571123.
This represents the nanoseconds from epoch (1970-01-01).
That is "2021-03-01T12:31:14.317571123" in ISO format

I want to convert it to boost::posix_time::ptime.
I know I could define a function like,

#include <boost/date_time/posix_time/posix_time.hpp>
#define BOOST_DATE_TIME_POSIX_TIME_STD_CONFIG

using namespace std;

namespace pt = boost::posix_time;
namespace gr = boost::gregorian;

pt::ptime from_nanos(const long long &nanos) {
    return pt::ptime(gr::date(1970, 1, 1)) + pt::time_duration(0, 0, 0, nanos);
}


But this requires me to define a macro BOOST_DATE_TIME_POSIX_TIME_STD_CONFIG that changes resolution from microseconds to nanoseconds.
I want to avoid this.
Are there any more robust solutions?

1

There are 1 best solutions below

1
sehe On BEST ANSWER

You already have the "correct" solution (although the code shown is incorrect, the define MUST precede any headers that may include Boost Datetime stuff).

Also note that

return pt::ptime(gr::date(1970, 1, 1)) + pt::time_duration(0, 0, 0, nanos);

should probably just be

return pt::ptime({1970, 1, 1}, pt::time_duration(0, 0, 0, nanos));

or indeed even

return {{1970, 1, 1}, {0, 0, 0, nanos}};

If you cannot use the define, you can always do a twostep: add seconds, and add fractional seconds later. That way you don't run into overflow issues with the default representation types.

Here's a tester: Live On Compiler Explorer

#include <boost/date_time/posix_time/posix_time.hpp>

using boost::posix_time::ptime;

ptime from_nanos_std(intmax_t nanos) {
    return {{1970, 1, 1}, {0, 0, 0, nanos}};
}

ptime from_nanos_man(intmax_t nanos) {
    constexpr auto NANO = 1'000'000'000;
#ifdef BOOST_DATE_TIME_POSIX_TIME_STD_CONFIG
    constexpr auto FRAC = 1;
#else
    constexpr auto FRAC = 1'000;
#endif
    return {{1970, 1, 1}, {0, 0, nanos / NANO, (nanos % NANO) / FRAC}};
}

#include <iostream>
int main() { 
    std::cout << "Expected: 2021-Mar-01 12:31:14.317571123\n";
#ifdef BOOST_DATE_TIME_POSIX_TIME_STD_CONFIG
    std::cout << "Standard: " << from_nanos_std(1614601874317571123) << "\n";
#endif
    std::cout << "Manual:   " << from_nanos_man(1614601874317571123) << "\n";
}

Output with -DBOOST_DATE_TIME_POSIX_TIME_STD_CONFIG:

Expected: 2021-Mar-01 12:31:14.317571123
Standard: 2021-Mar-01 12:31:14.317571123
Manual:   2021-Mar-01 12:31:14.317571123

Output without:

Expected: 2021-Mar-01 12:31:14.317571123
Manual:   2021-Mar-01 12:31:14.317571