Reputation: 2694
I have a bunch of time variables in the format "day-month-year H:M", for example, 14-03-15 15:25. How do I correctly measure the difference between two time variables and output a duration type?
std::string t1 = 14-03-15 15:25;
std::string t2 = 19-05-15 7:32;
template <typename Duration>
auto diff(std::string& t1, std::string& t2) {
// How to do from here?
}
auto ds = diff<std::chrono::seconds>(t1, t2);
auto dm = diff<std::chrono::minutes>(t1, t2);
Upvotes: 1
Views: 1842
Reputation: 219345
This question is interesting because it reveals how ambiguous questions about time can be.
Do t1
and t2
represent UTC times? Or times in time zones? If the latter, the computer's current local time zone, or some other time zone?
Although not likely to matter for these inputs, for the seconds-precision computation, do leap seconds matter?
The answer to each of these questions will impact the result. And the current C and C++ std API is inadequate to address the totality of these questions.
This library can give you the correct result, but can give different answers depending upon the desired interpretation of the input according to the above questions.
For the very simplest interpretation: these times represent UTC and leap seconds don't matter:
#include "date/date.h"
#include <chrono>
#include <iostream>
#include <sstream>
#include <stdexcept>
#include <string>
std::string t1 = "14-03-15 15:25";
std::string t2 = "19-05-15 7:32";
template <typename Duration>
auto
diff(const std::string& t1, const std::string& t2)
{
using namespace std;
using namespace date;
istringstream in{t1};
sys_time<Duration> d1;
in >> parse("%d-%m-%y %H:%M", d1);
if (in.fail())
throw runtime_error("didn't parse " + t1);
in.clear();
in.str(t2);
sys_time<Duration> d2;
in >> parse("%d-%m-%y %H:%M", d2);
if (in.fail())
throw runtime_error("didn't parse " + t2);
return d2 - d1;
}
int
main()
{
using date::operator<<;
auto ds = diff<std::chrono::seconds>(t1, t2);
std::cout << ds << '\n';
auto dm = diff<std::chrono::minutes>(t1, t2);
std::cout << dm << '\n';
}
And the output is:
5674020s
94567min
For slightly different inputs, computing assuming the input is in "America/New_York", the output would be different. And if t1
drifted prior to 01-01-15, then the matter of leap seconds can impact the output.
If these details of interpretation of input are important, you are practically guaranteed to get the computation wrong (but only slightly and rarely -- the most dangerous kind) with the existing C/C++ API.
Upvotes: 4
Reputation: 38911
After solving a problem with converting string to time
std::tm tm = {};
std::stringstream ss(t1);
ss >> std::get_time(&tm, "%d-%m-%y %H:%M");
auto tp1 = std::chrono::system_clock::from_time_t(std::mktime(&tm));
Or
std::tm tm = {};
strptime(t1.c_str(), "%d-%m-%y %H:%M", &tm);
auto tp1 = std::chrono::system_clock::from_time_t(std::mktime(&tm));
You can subtract clocks.
// floating-point duration: no duration_cast needed
std::chrono::duration<double, Duration> duration = tp2 - tp1;
Upvotes: 1