c++c++17c++-chronoctime

How to convert dd-mmm-yyyy and now() to days?


I need convert a dd-mmm-year string to epoch days to do some simple math. Specifically, calculate the number of days from now() to the date of the string.

I'm looking at <chrono> and <ctime> but am not seeing an obvious way to do that? How do you convert dd-mmm-year and now() to epoch days?


Solution

  • This can easily be done with this free, open-source, header-only preview of C++20 , which works with C++11/14/17:

    #include "date/date.h"
    #include <iostream>
    #include <sstream>
    
    int
    main()
    {
        using namespace date;
        using namespace std;
        using namespace std::chrono;
    
        string s1 = "25-Mar-2021";
        string s2 = "20-Jul-2021";
        istringstream in{s1};
        in.exceptions(ios::failbit);
        sys_days t1;
        in >> parse("%d-%b-%Y", t1);
        in.str(s2);
        in.clear();
        sys_days t2;
        in >> parse("%d-%b-%Y", t2);
        cout << t2 - t1 << '\n';
    }
    

    sys_days is a type alias for std::chrono::time_point<system_clock, duration<int, ratio<86400>>>. But you can think of it as a count of days since since 1970-01-01.

    The program above outputs:

    117d
    

    The type of the expression t2 - t1 is std::chrono::duration<int, ratio<86400>>.

    Here is a live example you can experiment with.

    Edit:

    You can convert durations (such as t2 - t1) to a signed integral type by using the .count() member function:

    auto i = (t2 - t1).count();  // 117
    

    Another way to do it is to divide by days{1}:

    auto i = (t2 - t1)/days{1};  // 117
    

    This latter technique gives those who know dimensional analysis a warm fuzzy feeling. :-)

    You can convert std::chrono::system_clock::now() to type sys_days like this:

    auto t2 = floor<days>(system_clock::now());
    

    This gives the current date according to UTC. If you need the current date according to some other time zone (such as the computer's local time zone setting), then that involves an additional library (at the same link) which is not header-only and involves some installation. In that case one would work in terms of local_days instead of sys_days:

    #include "date/tz.h"
    #include <iostream>
    #include <sstream>
    
    int
    main()
    {
        using namespace date;
        using namespace std;
        using namespace std::chrono;
    
        string s1 = "25-Mar-2021";
        istringstream in{s1};
        in.exceptions(ios::failbit);
        local_days t1;
        in >> parse("%d-%b-%Y", t1);
        auto t2 = floor<days>(current_zone()->to_local(system_clock::now()));
        cout << t2 - t1 << '\n';
    }
    

    Output (currently):

    1d