0

I am taking a system_clock time_point, converting it to a string, and then saving it to a configuration file.

Now I want to read that config file and turn the string back into a time point so that I can calculate the difference in time between two time points.

void SaveLastShuffleTime() {

    m_lastShuffleTime = std::chrono::system_clock::now();
    auto m_lastShuffleTimeTimeT = std::chrono::system_clock::to_time_t(m_lastShuffleTimeTimepoint);
    stringstream m_lastShuffeTimeSS;
    m_lastShuffeTimeSS << std::put_time(std::localtime(&m_lastShuffleTimeTimeT), "%Y-%m-%d %X");
    m_deviceStateSettings.UpdateDeviceStateSettings(LAST_SHUFFLE_TIME, m_lastShuffeTimeSS.str());
    
} 


void  CompareLastShuffleTime() {

    m _currentShuffleTime = std::chrono::system_clock::now();
    /* READ CONFIG FILE AND CONVERT BACK TO TIME POINT */
    int timeSinceLastShuffle = (duration_cast<minutes>(m_currentShuffleTime - m_oldShuffleTime)).count();
}

Please let me know if this is viable. The alternative is to save the timepoint as an integer but I would prefer not to do that.

Thanks

palacetrading
  • 71
  • 1
  • 11

3 Answers3

1

I recommend outputting UTC as opposed to local time so that the difference between timestamps isn't altered by UTC offset jumps (e.g. daylight saving).

C++20 makes this very easy, and allows timestamps with subsecond precision:

#include <cassert>
#include <chrono>
#include <iostream>
#include <sstream>

int
main()
{
    using namespace std;
    using namespace std::chrono;
    stringstream s;
    auto tp = system_clock::now();
    auto tp_save = tp;
    s << tp << '\n';          // Write it out
    tp = {};                  // Zero out the timestamp 
    s >> parse("%F %T", tp);  // Parse it back in
    assert(tp == tp_save);    // Make sure it is the same
    std::cout << s.str();     // This is what was formatted/parsed
}

Example output:

2021-06-17 16:10:10.562738

Vendors are still working on getting this out. But you can use this syntax today with C++11/14/17 and a free, open-source, header-only preview of this part of C++20.1

Just add:

  • #include "date/date.h"
  • using namespace date;

and the above works with the preview library.


1 Full disclosure: I am the lead author of this library. I am not pursuing any financial gain from this effort. But sometimes people get grumpy if I don't fully disclose this information.

Howard Hinnant
  • 206,506
  • 52
  • 449
  • 577
0
std::istringstream ss(str);
tm t;
ss >> std::get_time(&t, "%Y-%m-%dT%H:%M:%S");

std::time_t tt = std::mktime(&t);
/// If you don't need UTC time, just comment out the line below.
tt = std::mktime(std::gmtime(&tt));
return std::chrono::system_clock::from_time_t(tt);
ozan k
  • 485
  • 5
  • 18
  • 1
    adding some comments would be a good thing ;-) – schlebe Jun 17 '21 at 14:37
  • Not quite. The format strings need to match. Also , it's unclear why you are calling `tt = std::mktime(std::gmtime(&tt));` – AndyG Jun 17 '21 at 15:24
  • Thanks guys, I assumed OP would replace the format string with theirs. I will comment the gmtime, @AndyG, basically I need UTC time here in my implementation, so I convert it using gmtime. – ozan k Jun 17 '21 at 15:47
0

You could use cctz library. It provides convenient functions for formatting timepoint cctz::format to a string and parsing cctz::parse from a string. And also for working with timezones. Example:

#include <chrono>
#include <iostream>
#include <string>

#include "cctz/time_zone.h"

int main() {

  const std::chrono::system_clock::time_point now =
      std::chrono::system_clock::now();

  std::string now_str =
      cctz::format("%Y-%m-%d %H:%M:%S%z", now, cctz::utc_time_zone());
  std::cout << now_str << std::endl;

  std::chrono::system_clock::time_point tp;
  const bool ok =
      cctz::parse("%Y-%m-%d %H:%M:%S%z", now_str, cctz::utc_time_zone(), &tp);
  if (!ok)
    return -1;
}
alex_noname
  • 26,459
  • 5
  • 69
  • 86