Get time difference from specific day - c++

I am trying to find some utility in the chrono namespace to provide to my application the same feature I had in my C# program. What I need to do is to compute the time difference between to specific dates, but I can't find anything this specific. For example following is my C# code:
var startDate = new DateTime(2000, 1, 1);
int diffDays = (DateTime.Today.Date - startDate.Date).Days;
return diffDays.ToString();
Is there any equivalent function in C++?

// system_clock::from_time_t
#include <iostream>
#include <ctime>
#include <ratio>
#include <chrono>
int main ()
{
using namespace std::chrono;
// create tm with 1/1/2000:
std::tm timeinfo = std::tm();
timeinfo.tm_year = 100; // year: 2000
timeinfo.tm_mon = 0; // month: january
timeinfo.tm_mday = 1; // day: 1st
std::time_t tt = std::mktime (&timeinfo);
system_clock::time_point tp = system_clock::from_time_t (tt);
system_clock::duration d = system_clock::now() - tp;
// convert to number of days:
typedef duration<int,std::ratio<60*60*24>> days_type;
days_type ndays = duration_cast<days_type> (d);
// display result:
std::cout << ndays.count() << " days have passed since 1/1/2000";
std::cout << std::endl;
return 0;
}
Credits: http://www.cplusplus.com/reference/chrono/system_clock/from_time_t/

Here's an easier way to do this using this header-only open source lib:
#include "date.h"
#include <iostream>
int
main()
{
using namespace date;
using namespace std::chrono;
auto startDate = 2000_y/jan/1;
auto diffDays = floor<days>(system_clock::now()) - sys_days{startDate};
std::cout << diffDays.count() << '\n';
}
Currently outputs:
6138
Here is a wandbox link where you can paste the above code and try it out yourself using various versions of gcc and clang.

Related

C++ Checking if a string that is representing a date is 7 or more days before today date

I have a date stored as a string with the format %d.%m.%y, for example, "08.01.2022" and I want to check if at least 7 days have past since that day in C++.
I attempted using this method:
#include <iostream>
#include <time.h>
#include <stdio.h>
bool dateDifference(std::string stringDate, int days){
std::tm date; //tm
std::time_t today = std::time(0); //today
sscanf(stringDate,"%2d.%2m.%4y",&date.tm_mday,&date.tm_mon,&date.tm_year); //string to tm
std::time_t date_t = std::mktime(&date) //tm to time_t
return std::difftime(today, date_t) / (60 * 60 * 24) >= days; //return difference comparasion
}
void WinMain(){
if(dateDifference("05.01.2022", 7)){
//7 or more days have past since 05.01.2022
}
}
It seems to return false even if it should return true when the date is more than 7 days before today.
This answer doesn't actually attack your problem but offers an alternative solution using std::chrono (which would require C++20, and I think MSVC compiler for from_stream):
#include <chrono>
#include <ios> // boolalpha
#include <iostream> // cout
#include <sstream> // istringstream
#include <string>
int main()
{
namespace ch = std::chrono;
for (auto&& str : { "01.01.2022", "10.01.2022", "20.01.2022" })
{
std::istringstream iss{ str };
ch::year_month_day other_day{};
ch::from_stream(iss, "%d.%m.%Y", other_day);
const auto today = ch::sys_days{ ch::floor<ch::days>(ch::system_clock::now()) };
const auto delta = (today - ch::sys_days{ other_day }).count();
std::cout << std::boolalpha << (delta > 7) << ", " << delta << "\n";
}
}
// Outputs:
//
// true, 16
// false, 7
// false, -3
Or you could use Howard Hinnant's date library (C++11 onwards, header-only) together with std::chrono. This should work on any compiler, as demoed here.

how can i compare a start time with the system clock using ctime/chrono libaray

I'm running into a error trying to compile the program with conversion from double to int. What I want is to be able to display out the difference not just in seconds but in hours/minutes/seconds but I can't think of how to make the difftime work. If there is a better option like using chrono, I would appreciate the help.
#include <chrono>
#include <ctime>
#include <iomanip>
#include <iostream>
int main() {
std::tm now{},;
std::chrono::system_clock::time_point cc;
std::cout << "enter\nyear month day\n";
std::cin >> now.tm_year >> now.tm_mon >> now.tm_mday;
now.tm_year -= 1900;
now.tm_mon -= 1;
std::time_t n = std::mktime(&now);
cc = std::chrono::system_clock::from_time_t(n);
n = std::chrono::system_clock::to_time_t(cc);
std::cout << std::put_time(std::localtime(&n), "%FT%T") << "\n";
std::time_t system_time = time(nullptr);
std::cout << asctime(localtime(&system_time));
double fc = difftime(system_time, mktime(&now));
std::cout << "time diff "<< fc << endl;
}
You should checkout the date lib from howard hinnant.
https://github.com/HowardHinnant/date
The tz lib in it Can do your local time diff calculation in without converting it to utc. (normally you should always convert to utc before calculation, because of the daylight saving time) It also contains format functions to stream it in hour min sec format.
The better way of doing it is using a steady_clock instead of system_clock.
I don't know what your task is but you may use another class such as Stopwatch to generate elapsed time.
#include <chrono>
#include <ctime>
class StopWatch {
private:
chrono::time_point<chrono::steady_clock> start;
public:
void reset() { start = chrono::steady_clock::now(); }
StopWatch() { reset(); }
double elapsedSeconds() {
chrono::duration<double> d = chrono::steady_clock::now() - start;
return chrono::duration_cast<chrono::microseconds>(d).count() / 1000000.;
}};
After that, you can simply use Stopwatch:
int main(void){
Stopwatch s;
cout<<s.elapsedSeconds();
}

Get start of day timestamp c++

I need to get timestamp in c++. I've found some functions in chrono for example:
std::chrono::system_clock::now()
But it's returning current time. How to get timestamp for a day? I mean the time that represents 00:00:00 of today and the same for yesterday? I'm very new to c++..
I think, you just need date, without time. So, you can get it like this:
#include <chrono>
#include <ctime>
#include <iomanip>
#include <iostream>
using namespace std;
int main()
{
auto curr = std::chrono::system_clock::now();
auto tm = std::chrono::system_clock::to_time_t(curr);
cout << std::put_time(std::localtime(&tm), "%d.%m.%Y");
}
and, of course, you can forcibly reset the fields of time, if you need:
auto curr = std::chrono::system_clock::now();
time_t tm = std::chrono::system_clock::to_time_t(curr);
auto lt = std::localtime(&tm);
lt->tm_hour = 0;
lt->tm_min = 0;
lt->tm_sec = 0;
cout << lt->tm_mday << "." << lt->tm_mon + 1 << "." << lt->tm_year + 1900 << endl;

convert Date to time in millisecond in c++?

I have a requirement where I have to convert given string in date time format to milliseconds from epoch.
In Javascript there is date to time conversion api but in c++ I couldn't find anything as such.
Input would look like '2016-Mar-15 09:23:58.665068'
output should be in milliseconds say 14520000785.
I have tried looking into boost but still couldn't find(or understand) how to do?
Also, going through google I find the other way round i.e. converting milliseconds to date format but not what I require nor any helpful post for same.
Any help will be much appreciated.
Using only standard library features:
#include <ctime>
#include <chrono>
#include <iostream>
int main()
{
std::tm tm = {};
const char* snext = ::strptime("2016-Mar-15 09:23:58.665068", "%Y-%b-%d %H:%M:%S", &tm);
auto time_point = std::chrono::system_clock::from_time_t(std::mktime(&tm));
long long duration_ms = time_point.time_since_epoch() / std::chrono::milliseconds(1) + std::atof(snext) * 1000.0f;
std::cout << duration_ms << std::endl;
}
Prints: 1458033838665
See std::chrono::system_clock::now and std::chrono::milliseconds.
Most straightforward would be to just spell it out:
auto pt = boost::lexical_cast<ptime>("2016-Mar-15 09:23:58.665068");
std::cout << (pt - ptime { {1970,0,0}, {} }).total_milliseconds();
Live On Coliru
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/date_time/posix_time/posix_time_io.hpp>
#include <boost/date_time.hpp>
#include <sstream>
int main() {
using boost::posix_time::ptime;
ptime pt;
{
std::istringstream iss("2016-Mar-15 09:23:58.665068");
auto* f = new boost::posix_time::time_input_facet("%Y-%b-%d %H:%M:%S%f");
std::locale loc(std::locale(""), f);
iss.imbue(loc);
iss >> pt;
}
std::cout << pt << " " << (pt - ptime{{1970,1,1},{}}).total_milliseconds();
}
Prints
2016-Mar-15 09:23:58.665068 1458033838665
Of course, extract the parsing in a helper function. Keep the locale around for reuse etc.

How to convert std::chrono::time_point to calendar datetime string with fractional seconds?

How to convert std::chrono::time_point to calendar datetime string with fractional seconds?
For example:
"10-10-2012 12:38:40.123456"
If system_clock, this class have time_t conversion.
#include <iostream>
#include <chrono>
#include <ctime>
using namespace std::chrono;
int main()
{
system_clock::time_point p = system_clock::now();
std::time_t t = system_clock::to_time_t(p);
std::cout << std::ctime(&t) << std::endl; // for example : Tue Sep 27 14:21:13 2011
}
example result:
Thu Oct 11 19:10:24 2012
EDIT:
But, time_t does not contain fractional seconds.
Alternative way is to use time_point::time_since_epoch() function. This function returns duration from epoch.
Follow example is milli second resolution's fractional.
#include <iostream>
#include <chrono>
#include <ctime>
using namespace std::chrono;
int main()
{
high_resolution_clock::time_point p = high_resolution_clock::now();
milliseconds ms = duration_cast<milliseconds>(p.time_since_epoch());
seconds s = duration_cast<seconds>(ms);
std::time_t t = s.count();
std::size_t fractional_seconds = ms.count() % 1000;
std::cout << std::ctime(&t) << std::endl;
std::cout << fractional_seconds << std::endl;
}
example result:
Thu Oct 11 19:10:24 2012
925
Self-explanatory code follows which first creates a std::tm corresponding to 10-10-2012 12:38:40, converts that to a std::chrono::system_clock::time_point, adds 0.123456 seconds, and then prints that out by converting back to a std::tm. How to handle the fractional seconds is in the very last step.
#include <iostream>
#include <chrono>
#include <ctime>
int main()
{
// Create 10-10-2012 12:38:40 UTC as a std::tm
std::tm tm = {0};
tm.tm_sec = 40;
tm.tm_min = 38;
tm.tm_hour = 12;
tm.tm_mday = 10;
tm.tm_mon = 9;
tm.tm_year = 112;
tm.tm_isdst = -1;
// Convert std::tm to std::time_t (popular extension)
std::time_t tt = timegm(&tm);
// Convert std::time_t to std::chrono::system_clock::time_point
std::chrono::system_clock::time_point tp =
std::chrono::system_clock::from_time_t(tt);
// Add 0.123456 seconds
// This will not compile if std::chrono::system_clock::time_point has
// courser resolution than microseconds
tp += std::chrono::microseconds(123456);
// Now output tp
// Convert std::chrono::system_clock::time_point to std::time_t
tt = std::chrono::system_clock::to_time_t(tp);
// Convert std::time_t to std::tm (popular extension)
tm = std::tm{0};
gmtime_r(&tt, &tm);
// Output month
std::cout << tm.tm_mon + 1 << '-';
// Output day
std::cout << tm.tm_mday << '-';
// Output year
std::cout << tm.tm_year+1900 << ' ';
// Output hour
if (tm.tm_hour <= 9)
std::cout << '0';
std::cout << tm.tm_hour << ':';
// Output minute
if (tm.tm_min <= 9)
std::cout << '0';
std::cout << tm.tm_min << ':';
// Output seconds with fraction
// This is the heart of the question/answer.
// First create a double-based second
std::chrono::duration<double> sec = tp -
std::chrono::system_clock::from_time_t(tt) +
std::chrono::seconds(tm.tm_sec);
// Then print out that double using whatever format you prefer.
if (sec.count() < 10)
std::cout << '0';
std::cout << std::fixed << sec.count() << '\n';
}
For me this outputs:
10-10-2012 12:38:40.123456
Your std::chrono::system_clock::time_point may or may not be precise enough to hold microseconds.
Update
An easier way is to just use this date library. The code simplifies down to (using C++14 duration literals):
#include "date.h"
#include <iostream>
#include <type_traits>
int
main()
{
using namespace date;
using namespace std::chrono;
auto t = sys_days{10_d/10/2012} + 12h + 38min + 40s + 123456us;
static_assert(std::is_same<decltype(t),
time_point<system_clock, microseconds>>{}, "");
std::cout << t << '\n';
}
which outputs:
2012-10-10 12:38:40.123456
You can skip the static_assert if you don't need to prove that the type of t is a std::chrono::time_point.
If the output isn't to your liking, for example you would really like dd-mm-yyyy ordering, you could:
#include "date.h"
#include <iomanip>
#include <iostream>
int
main()
{
using namespace date;
using namespace std::chrono;
using namespace std;
auto t = sys_days{10_d/10/2012} + 12h + 38min + 40s + 123456us;
auto dp = floor<days>(t);
auto time = make_time(t-dp);
auto ymd = year_month_day{dp};
cout.fill('0');
cout << ymd.day() << '-' << setw(2) << static_cast<unsigned>(ymd.month())
<< '-' << ymd.year() << ' ' << time << '\n';
}
which gives exactly the requested output:
10-10-2012 12:38:40.123456
Update
Here is how to neatly format the current time UTC with milliseconds precision:
#include "date.h"
#include <iostream>
int
main()
{
using namespace std::chrono;
std::cout << date::format("%F %T\n", time_point_cast<milliseconds>(system_clock::now()));
}
which just output for me:
2016-10-17 16:36:02.975
C++17 will allow you to replace time_point_cast<milliseconds> with floor<milliseconds>. Until then date::floor is available in "date.h".
std::cout << date::format("%F %T\n", date::floor<milliseconds>(system_clock::now()));
Update C++20
In C++20 this is now simply:
#include <chrono>
#include <iostream>
int
main()
{
using namespace std::chrono;
auto t = sys_days{10d/10/2012} + 12h + 38min + 40s + 123456us;
std::cout << t << '\n';
}
Or just:
std::cout << std::chrono::system_clock::now() << '\n';
std::format will be available to customize the output.
In general, you can't do this in any straightforward fashion. time_point is essentially just a duration from a clock-specific epoch.
If you have a std::chrono::system_clock::time_point, then you can use std::chrono::system_clock::to_time_t to convert the time_point to a time_t, and then use the normal C functions such as ctime or strftime to format it.
Example code:
std::chrono::system_clock::time_point tp = std::chrono::system_clock::now();
std::time_t time = std::chrono::system_clock::to_time_t(tp);
std::tm timetm = *std::localtime(&time);
std::cout << "output : " << std::put_time(&timetm, "%c %Z") << "+"
<< std::chrono::duration_cast<std::chrono::milliseconds>(tp.time_since_epoch()).count() % 1000 << std::endl;
This worked for me for a format like YYYY.MM.DD-HH.MM.SS.fff. Attempting to make this code capable of accepting any string format will be like reinventing the wheel (i.e. there are functions for all this in Boost.
std::chrono::system_clock::time_point string_to_time_point(const std::string &str)
{
using namespace std;
using namespace std::chrono;
int yyyy, mm, dd, HH, MM, SS, fff;
char scanf_format[] = "%4d.%2d.%2d-%2d.%2d.%2d.%3d";
sscanf(str.c_str(), scanf_format, &yyyy, &mm, &dd, &HH, &MM, &SS, &fff);
tm ttm = tm();
ttm.tm_year = yyyy - 1900; // Year since 1900
ttm.tm_mon = mm - 1; // Month since January
ttm.tm_mday = dd; // Day of the month [1-31]
ttm.tm_hour = HH; // Hour of the day [00-23]
ttm.tm_min = MM;
ttm.tm_sec = SS;
time_t ttime_t = mktime(&ttm);
system_clock::time_point time_point_result = std::chrono::system_clock::from_time_t(ttime_t);
time_point_result += std::chrono::milliseconds(fff);
return time_point_result;
}
std::string time_point_to_string(std::chrono::system_clock::time_point &tp)
{
using namespace std;
using namespace std::chrono;
auto ttime_t = system_clock::to_time_t(tp);
auto tp_sec = system_clock::from_time_t(ttime_t);
milliseconds ms = duration_cast<milliseconds>(tp - tp_sec);
std::tm * ttm = localtime(&ttime_t);
char date_time_format[] = "%Y.%m.%d-%H.%M.%S";
char time_str[] = "yyyy.mm.dd.HH-MM.SS.fff";
strftime(time_str, strlen(time_str), date_time_format, ttm);
string result(time_str);
result.append(".");
result.append(to_string(ms.count()));
return result;
}
I would have put this in a comment on the accepted answer, since that's where it belongs, but I can't. So, just in case anyone gets unreliable results, this could be why.
Be careful of the accepted answer, it fails if the time_point is before the epoch.
This line of code:
std::size_t fractional_seconds = ms.count() % 1000;
will yield unexpected values if ms.count() is negative (since size_t is not meant to hold negative values).
In my case I use chrono and c function localtime_r which is thread-safe (in opposition to std::localtime).
#include <iostream>
#include <chrono>
#include <ctime>
#include <time.h>
#include <iomanip>
int main() {
std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
std::time_t currentTime = std::chrono::system_clock::to_time_t(now);
std::chrono::milliseconds now2 = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch());
struct tm currentLocalTime;
localtime_r(&currentTime, &currentLocalTime);
char timeBuffer[80];
std::size_t charCount { std::strftime( timeBuffer, 80,
"%b %d %T",
&currentLocalTime)
};
if (charCount == 0) return -1;
std::cout << timeBuffer << "." << std::setfill('0') << std::setw(3) << now2.count() % 1000 << std::endl;
return 0;
}
If you are to format a system_clock::time_point in the format of numpy datetime64, you could use:
std::string format_time_point(system_clock::time_point point)
{
static_assert(system_clock::time_point::period::den == 1000000000 && system_clock::time_point::period::num == 1);
std::string out(29, '0');
char* buf = &out[0];
std::time_t now_c = system_clock::to_time_t(point);
std::strftime(buf, 21, "%Y-%m-%dT%H:%M:%S.", std::localtime(&now_c));
sprintf(buf+20, "%09ld", point.time_since_epoch().count() % 1000000000);
return out;
}
sample output: 2019-11-19T17:59:58.425802666