Home > database >  How to add days, years, hours to boost::ptime?
How to add days, years, hours to boost::ptime?

Time:07-29

For example i have ptime("2000-10-10 00:00:00"). How i can add to this ptime? For example "0001-00-01 00:00:00" - one year and one day, and i can use only this format cuz i get string like "yyyy-mm-dd hh:mm:ss" or in timestamp_t(uin64_t). In main func i write example how i see this.

constexpr const char format[] = "%Y-%m-%d %H:%M:%S";

bt::ptime from_string_dtime(const std::string& s);

class date_time
{
public:
    date_time() = default;
    date_time(const std::string& dtime);
    date_time(const bt::ptime& ptime);
    
    ~date_time() = default;
    
    api::timestamp_t to_timestamp();

public:

    friend date_time operator  (const date_time& lv, uint64_t rv);
    
private:
    bt::ptime d_time;
};


    bt::ptime from_string_dtime(const std::string& s)
{
    bt::ptime pt;
    std::istringstream is(s);
    is.exceptions(std::ifstream::failbit | std::ifstream::badbit);
    is.imbue(std::locale(std::locale::classic(), new bt::time_input_facet(format)));
    is >> pt;
    return pt;
}

date_time::date_time(const std::string& dtime)
:   d_time(from_string_dtime(dtime))
{}

date_time::date_time(const bt::ptime& ptime)
:   d_time(ptime)
{}

api::timestamp_t date_time::to_timestamp() {     
    const bt::ptime epoch = bt::from_time_t(0);
    bt::time_duration duration = d_time - epoch;
    return duration.total_seconds(); 
}

date_time operator  (const date_time& lv, uint64_t rv)
{
    return date_time(lv.d_time   bt::milliseconds(rv));
}

int main()
{
    nup::core::date_time dtime("0000-00-01 00:00:01"); // Exception here, i understand why, but idk how resolve
    nup::core::date_time dtime2("2004-04-22 00:00:01");
    nup::core::date_time dtime3("2004-04-23 00:00:02");
    
    //i want smth like this
    (dtime   dtime2) == dtime(3)

}

CodePudding user response:

nup::core::date_time dtime("0000-00-01 00:00:01"); // Exception here, i understand why, but idk how resolve

The problem is that you're trying to treat something that is not a date-time as a... date_time. Parse a duration instead!

struct duration {
    unsigned          y, m, d;
    bt::time_duration tod;
};

duration parse_duration(std::string_view sv) {
    namespace x3 = boost::spirit::x3;
    static const x3::uint_parser<unsigned short, 10, 4, 4> u4{};
    static const x3::uint_parser<unsigned short, 10, 2, 2> u2{};

    duration result;
    unsigned short H, M, S;
    auto tied = std::tie(result.y, result.m, result.d, H, M, S);

    if (!x3::parse(begin(sv), end(sv),
                  u4 >> '-' >> u2 >> '-' >> u2 >> ' ' >> //
                      u2 >> ':' >> u2 >> ':' >> u2 >> x3::eoi,
                  tied))
    {
        throw std::runtime_error("invalid time duration");
    }
    result.tod = bt::hours(H)   bt::minutes(M)   bt::seconds(S);
    return result;
}

Now you can implement operator :

friend date_time operator (const date_time& lv, duration const& rv) {
    return lv.d_time   //
        bg::years(rv.y)   bg::months(rv.m)   bg::days(rv.d)   rv.tod;
}

Live Demo

Live On Coliru

#include <boost/date_time/gregorian/gregorian_io.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/date_time/posix_time/posix_time_io.hpp>
#include <boost/fusion/adapted/std_tuple.hpp>
#include <boost/spirit/home/x3.hpp>
#include <sstream>

namespace bg = boost::gregorian;
namespace bt = boost::posix_time;

namespace nup::core {
    constexpr const char format[] = "%Y-%m-%d %H:%M:%S";

    bt::ptime from_string_dtime(const std::string& s);

    struct duration {
        unsigned          y, m, d;
        bt::time_duration tod;
    };

    duration parse_duration(std::string_view sv) {
        namespace x3 = boost::spirit::x3;
        static const x3::uint_parser<unsigned short, 10, 4, 4> u4{};
        static const x3::uint_parser<unsigned short, 10, 2, 2> u2{};

        duration result;
        unsigned short H, M, S;
        auto tied = std::tie(result.y, result.m, result.d, H, M, S);

        if (!x3::parse(begin(sv), end(sv),
                      u4 >> '-' >> u2 >> '-' >> u2 >> ' ' >> //
                          u2 >> ':' >> u2 >> ':' >> u2 >> x3::eoi,
                      tied))
        {
            throw std::runtime_error("invalid time duration");
        }
        result.tod = bt::hours(H)   bt::minutes(M)   bt::seconds(S);
        return result;
    }

    class date_time {
      public:
        date_time() = default;
        ~date_time() = default;
        date_time(const std::string& dtime)
            : d_time(from_string_dtime(dtime)) {}

        date_time(const bt::ptime& ptime) : d_time(ptime) {}

        auto to_timestamp() {
            const bt::ptime   epoch    = bt::from_time_t(0);
            bt::time_duration duration = d_time - epoch;
            return duration.total_seconds();
        }

      public:
        friend date_time operator (const date_time& lv, duration const& rv) {
            return lv.d_time   //
                bg::years(rv.y)   bg::months(rv.m)   bg::days(rv.d)   rv.tod;
        }
        friend std::ostream& operator<<(std::ostream& os, date_time const& dt) {
            return os << dt.d_time;
        }

      private:
        bt::ptime d_time;
    };

    bt::ptime from_string_dtime(const std::string& s) {
        bt::ptime          pt;
        std::istringstream is(s);
        is.exceptions(std::ios::failbit | std::ios::badbit);
        is.imbue(std::locale(std::locale::classic(),
                             new bt::time_input_facet(format)));
        is >> pt;
        return pt;
    }

} // namespace nup::core

int main()
{
    auto dtime = nup::core::parse_duration("0000-00-01 00:00:01");

    nup::core::date_time dtime2("2004-04-22 00:00:01");
    nup::core::date_time dtime3("2004-04-23 00:00:02");

    std::cout << "dtime:            " << dtime.y          << "-"   << dtime.m << "-" << dtime.d << " " << dtime.tod << "\n";
    std::cout << "dtime2:           " << dtime2           << "\n";
    std::cout << "(dtime2   dtime): " << (dtime2   dtime) << "\n";
    std::cout << "dtime3:           " << dtime3           << "\n";
}

Prints

dtime:            0-0-1 00:00:01
dtime2:           2004-Apr-22 00:00:01
(dtime2   dtime): 2004-Apr-23 00:00:02
dtime3:           2004-Apr-23 00:00:02
  • Related