2

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?

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
buttonsrtoys
  • 2,359
  • 3
  • 32
  • 52
  • Does this answer your question? [Using momentjs to convert date to epoch then back to date](https://stackoverflow.com/questions/26392280/using-momentjs-to-convert-date-to-epoch-then-back-to-date) – Ali Mar 25 '21 at 20:14
  • `epoch days` are days since epoch? Ie. seconds since epoch divided by seconds in a day? – KamilCuk Mar 26 '21 at 13:20

1 Answers1

3

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
Howard Hinnant
  • 206,506
  • 52
  • 449
  • 577
  • Thanks @Howard. Looks like just what I need. `t2 - t1` results in a `date::days` type--how do I convert this to `int`? Also, would you mind changing your example to make `s2` equal to `now()` like I mentioned in my OP? I need to calc from today to the given date. – buttonsrtoys Mar 26 '21 at 01:26
  • I think a call to `locale("LC_ALL=C")` is needed. – KamilCuk Mar 26 '21 at 13:20
  • Only if you want to ensure that the "C" month name abbreviations are read and you've set the global local to something else. Alternatively you could imbue `in` with the desired locale, and avoid global settings. – Howard Hinnant Mar 26 '21 at 14:05