I'm new in C++, and i have a problem with Unixtime adding. For example, I have a date 8.10.2014 14:49
I need to add 26 days, 12 hours, 44 minutes to it. This is my code:
#include <iostream>
#include <ctime>
struct Date {
int Minute;
int Hour;
int Day;
int Month;
int Year;
};
int main(){
time_t rawtime;
struct tm * timeinfo;
Date startDate;
std::cin >> startDate.Year;
std::cin >> startDate.Month;
std::cin >> startDate.Day;
std::cin >> startDate.Hour;
std::cin >> startDate.Minute;
time ( &rawtime );
timeinfo = localtime ( &rawtime );
timeinfo->tm_year = startDate.Year - 1900;
timeinfo->tm_mon = startDate.Month -1;
timeinfo->tm_mday = startDate.Day;
timeinfo->tm_hour = startDate.Hour;
timeinfo->tm_min = startDate.Minute;
rawtime = mktime ( timeinfo ) + 2555027;
std::cout << rawtime << std::endl;
struct tm *tm = localtime(&rawtime);
char date[80];
strftime(date, sizeof(date), "%Y %m %d %H %M", tm);
std::cout << date;
}
The answers is approximately similar to the truth, but don't correct. Why?
If you have C++11 (or C++14) and a relatively up-to-date compiler, you can use this library:
http://howardhinnant.github.io/date/tz.html
like so:
#include <chrono>
#include <iostream>
#include "tz.h"
int
main()
{
using namespace date;
using namespace std::chrono_literals;
auto zone = current_zone();
auto time = make_zoned(current_zone(), local_days{8_d/10/2014} + 14h + 49min);
time = time.get_sys_time() + days{26} + 12h + 44min;
std::cout << time << '\n';
}
This is roughly equivalent to what you have, which assumes that the date you specified is in your computer's local timezone, and that you also want the results in your computer's local timezone. For me this outputs:
2014-11-04 02:33:00 EST
However you also mentioned "Unixtime", which to me means Unix time. This time is measured in UTC, which lacks complications such as daylight saving time. If it is the intent to do this in Unix time, you can do this more easily and cheaply with this library:
http://howardhinnant.github.io/date/date.html
like this:
#include <chrono>
#include <iostream>
#include "date.h"
int
main()
{
using namespace date;
using namespace std::chrono_literals;
auto time = sys_days{8_d/10/2014} + 14h + 49min + days{26} + 12h + 44min;
std::cout << time << '\n';
}
which will portably output:
2014-11-04 03:33
The use of the "chrono literals" (e.g. 14h) implies C++14. If you are in C++11, you can substitute in the more verbose hours{14} (hours is in namespace std::chrono). If you are in C++03, well, then, never mind. :-)
Related
I have a chunk of code where I am trying to convert the string time into time_t and then use the difftime() method to do a comparison. However, currently, the difftime returns 0 instead of the number of seconds differences. Can someone help me on this please.
Here's my C++ code:
const char *time_details = "16:35:12";
const char *another_time = "18:35:15";
struct tm tm = { 0 };
struct tm tm1 = { 0 };
istringstream ss(time_details);
istringstream ss1(another_time);
ss >> get_time(&tm, "%H:%M:%S"); // or just %T in this case
ss1 >> get_time(&tm1, "%H:%M:%S");
std::time_t time1 = mktime(&tm);
std::time_t time2 = mktime(&tm1);
double a = difftime(time2, time1);
cout << "the diff is : " << a;
I am following this stackoverflow solution as my reference. Really appreciate your helps on this one.
Maybe your compiler version is too low.I have no problem compiling the following code in g++ 9.
#include <ctime>
#include <sstream>
#include <iomanip>
#include <time.h>
#include <iostream>
using namespace std;
int main()
{
const char *time_details = "16:35:12";
const char *another_time = "18:35:15";
struct tm tm = { 0 };
struct tm tm1 = { 0 };
istringstream ss(time_details);
istringstream ss1(another_time);
ss >> get_time(&tm, "%H:%M:%S"); // or just %T in this case
ss1 >> get_time(&tm1, "%H:%M:%S");
std::time_t time1 = mktime(&tm);
std::time_t time2 = mktime(&tm1);
double a = difftime(time2, time1);
cout << "the diff is : " << a;
return 0;
}
The output is the diff is : 7203
I have PostgreSQL timestamp string:
2020-07-06 09:30:00.646533
I'm trying to convert it to timeval struct, I tried using this answer, but I'm getting this output:
Thu Jan 1 00:33:40 1970
This is my code:
#include <iostream>
int main()
{
std::string ss("2020-07-06 09:30:00.646533");
auto t = atoll(ss.c_str());
time_t time = atoi(ss.c_str());
std::cout << asctime(gmtime(&time));
return 0;
}
When running with debugger, I see that this line
auto t = atoll(ss.c_str());
isn't working/set time with values.
How can i fix it?
atoll and atoi simply parse integers of various sizes from a string. They aren't great functions to use in general as they have no way of indicating that they have failed to parse the string. std::stoi and friends are the better functions to use. However in this case we don't have a number we have a date string so std::stoi won't work either (but it can at least tell you it didn't work).
c++20 comes with much better date support, until then Howard Hinnant's date library provides the same functionality:
#include "date.h"
#include <iostream>
#include <sstream>
#include <chrono>
int main()
{
std::stringstream ss("2020-07-06 09:30:00.646533");
// convert string to date time
std::chrono::system_clock::time_point time;
ss >> date::parse("%F %T", time);
if (!ss) {
std::cout << "invalid date\n";
return 1;
}
// get the amount of time since the epoch, assumes std::chrono::system_clock uses the same epoch as timeval
auto sinceEpoch = time.time_since_epoch();
// get the whole number of seconds
auto seconds = date::floor<std::chrono::seconds>(sinceEpoch);
// get the remaining microseconds
auto microseconds = std::chrono::duration_cast<std::chrono::microseconds>(sinceEpoch - seconds);
std::cout << seconds.count() << ", " << microseconds.count() << "\n";
return 0;
}
If you must re-invent the wheel you can do it using the pre c++20 standard library:
#include <iostream>
#include <sstream>
#include <chrono>
#include <iomanip>
int main()
{
std::stringstream ss("2020-07-06 09:30:00.646533");
std::tm tm;
// convert string to date time
std::chrono::system_clock::time_point time;
double fraction;
ss >> std::get_time(&tm, "%Y-%m-%d %H:%M:%S") >> fraction;
if (!ss) {
std::cout << "invalid date\n";
return 1;
}
time_t seconds = mktime(&tm);
int64_t microseconds = fraction * 1'000'000;
std::cout << seconds << ", " << microseconds << "\n";
return 0;
}
Note that the microseconds should really be parsed as an integer not a double but you have to be careful to handle strings with different numbers of digits after the decimal point and with leading zeros.
you can use like this:
#include<ctime>
#include<iotream>
int main()
{
std::string ss = "2020-07-06 09:30:00.646533";
auto i = ss.find_first_of('.');
std::string line(ss.begin()+(i+1),ss.end());
std::tm tm = {};
tm.tm_isdst = -1; // <- to set not to use day lghite saveing.
strptime(ss.c_str(), "%F %H:%M:%S", &tm); //<-enter the data to tm
start.tv_sec = mktime(&tm); //<-convert tm to time_t
start.tv_usec = stoi(line); // <- set the usec from the stirng
//IF you want the other why around
strftime(tmbuf, sizeof tmbuf, " %F %H:%M:%S", localtime(&start.tv_sec));
snprintf(buf, sizeof buf, "%s.%06ld", tmbuf, start.tv_usec);
std::cout << tmbuf;
return 0;
}
output:
2020-07-06 09:30:00.646533
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(¤tTime, ¤tLocalTime);
char timeBuffer[80];
std::size_t charCount { std::strftime( timeBuffer, 80,
"%b %d %T",
¤tLocalTime)
};
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
I know this may be simple but being C++ I doubt it will be. How do I convert a string in the form 01/01/2008 to a date so I can manipulate it? I am happy to break the string into the day month year constituents. Also happy if solution is Windows only.
#include <time.h>
char *strptime(const char *buf, const char *format, struct tm *tm);
I figured it out without using strptime.
Break the date down into its components i.e. day, month, year, then:
struct tm tm;
time_t rawtime;
time ( &rawtime );
tm = *localtime ( &rawtime );
tm.tm_year = year - 1900;
tm.tm_mon = month - 1;
tm.tm_mday = day;
mktime(&tm);
tm can now be converted to a time_t and be manipulated.
For everybody who is looking for strptime() for Windows, it requires the source of the function itself to work. The latest NetBSD code does not port to Windows easily, unfortunately.
I myself have used the implementation here (strptime.h and strptime.c).
Another helpful piece of code can be found here. This comes originally from Google Codesearch, which does not exist anymore.
Hope this saves a lot of searching, as it took me quite a while to find this (and most often ended up at this question).
#include <time.h>
#include <iostream>
#include <sstream>
#include <algorithm>
using namespace std;
int main ()
{
time_t rawtime;
struct tm * timeinfo;
int year, month ,day;
char str[256];
cout << "Inter date: " << endl;
cin.getline(str,sizeof(str));
replace( str, str+strlen(str), '/', ' ' );
istringstream( str ) >> day >> month >> year;
time ( &rawtime );
timeinfo = localtime ( &rawtime );
timeinfo->tm_year = year - 1900;
timeinfo->tm_mon = month - 1;
timeinfo->tm_mday = day;
mktime ( timeinfo );
strftime ( str, sizeof(str), "%A", timeinfo );
cout << str << endl;
system("pause");
return 0;
}
Why not go for a simpler solution using boost
using namespace boost::gregorian;
using namespace boost::posix_time;
ptime pt = time_from_string("20150917");
You can utilize the boost library(cross platform)
#include <stdio.h>
#include "boost/date_time/posix_time/posix_time.hpp"
int main()
{
std::string strTime = "2007-04-11 06:18:29.000";
std::tm tmTime = boost::posix_time::to_tm(boost::posix_time::time_from_string(strTime));
return 0;
}
But the format should be as mentioned :)
I know this may be simple but being C++ I doubt it will be. How do I convert a string in the form 01/01/2008 to a date so I can manipulate it? I am happy to break the string into the day month year constituents. Also happy if solution is Windows only.
#include <time.h>
char *strptime(const char *buf, const char *format, struct tm *tm);
I figured it out without using strptime.
Break the date down into its components i.e. day, month, year, then:
struct tm tm;
time_t rawtime;
time ( &rawtime );
tm = *localtime ( &rawtime );
tm.tm_year = year - 1900;
tm.tm_mon = month - 1;
tm.tm_mday = day;
mktime(&tm);
tm can now be converted to a time_t and be manipulated.
For everybody who is looking for strptime() for Windows, it requires the source of the function itself to work. The latest NetBSD code does not port to Windows easily, unfortunately.
I myself have used the implementation here (strptime.h and strptime.c).
Another helpful piece of code can be found here. This comes originally from Google Codesearch, which does not exist anymore.
Hope this saves a lot of searching, as it took me quite a while to find this (and most often ended up at this question).
#include <time.h>
#include <iostream>
#include <sstream>
#include <algorithm>
using namespace std;
int main ()
{
time_t rawtime;
struct tm * timeinfo;
int year, month ,day;
char str[256];
cout << "Inter date: " << endl;
cin.getline(str,sizeof(str));
replace( str, str+strlen(str), '/', ' ' );
istringstream( str ) >> day >> month >> year;
time ( &rawtime );
timeinfo = localtime ( &rawtime );
timeinfo->tm_year = year - 1900;
timeinfo->tm_mon = month - 1;
timeinfo->tm_mday = day;
mktime ( timeinfo );
strftime ( str, sizeof(str), "%A", timeinfo );
cout << str << endl;
system("pause");
return 0;
}
Why not go for a simpler solution using boost
using namespace boost::gregorian;
using namespace boost::posix_time;
ptime pt = time_from_string("20150917");
You can utilize the boost library(cross platform)
#include <stdio.h>
#include "boost/date_time/posix_time/posix_time.hpp"
int main()
{
std::string strTime = "2007-04-11 06:18:29.000";
std::tm tmTime = boost::posix_time::to_tm(boost::posix_time::time_from_string(strTime));
return 0;
}
But the format should be as mentioned :)