I'm trying to convert a UNIX Timestamp which is in long to a Date Time string that needs to be stored in MySQL, in this format 2016-02-01 03:15:10
This is what i have so far. Its not working on the time extraction part. I couldn't find any constructor for boost::posix_time::time_duration that can take directly a boost::posix_time::ptime object. So i tried to include a workaround. But it doesn't work in the hours() part.
static inline std::string getDateTime(long timestamp) {
std::stringstream date_str;
boost::posix_time::ptime pt_1 = boost::posix_time::from_time_t(timestamp);
/* workaround to somehow get a time_duration object constructed */
boost::posix_time::ptime pt_temp = boost::posix_time::from_time_t(0);
boost::gregorian::date d = pt_1.date();
boost::posix_time::time_duration td = pt_1 - pt_temp;
/* construct the Date Time string */
date_str << d.year() << "-" << std::setw(2) << std::setfill('0') << d.month().as_number() << "-" << std::setw(2) << std::setfill('0') << d.day() << " "
<< td.hours() << ":" << td.minutes() << ":" << td.seconds();
return date_str.str();
}
With an Timestamp input such as 1455892259 i'm getting this 2016-02-19 404414:30:59 as a DateTime String from the function. How to actually get the correct Date Time string which in this case would be 2016-02-19 14:30:59. Using Boost for this is compulsory.
UPDATE
This is the final working function rewritten using the answer provided by Jarra McIntyre below.
static inline std::string getDateTime(long timestamp) {
std::stringstream date_str;
boost::posix_time::ptime pt_1 = boost::posix_time::from_time_t(timestamp);
boost::gregorian::date d = pt_1.date();
auto td = pt_1.time_of_day();
/* construct the Date Time string */
date_str << d.year() << "-" << std::setw(2) << std::setfill('0') << d.month().as_number() << "-" << std::setw(2) << std::setfill('0') << d.day() << " "
<< td.hours() << ":" << td.minutes() << ":" << td.seconds();
return date_str.str();
}
Use
auto td = pt_1.time_of_day();
There is no need for a workaround to get the time of day. The number of hours being displayed in your question is probably the number of hours between 1970-01-01 00:00 and 2016-02-19 14:00. For your method of getting the time_duration to work you would have to construct a ptime on the same day not at unix time 0.
Related
This might sound like a basic question but I've searched a lot. I am trying to time-profile a function call in C++ & need to log the time in seconds up to 3 decimal places. For example 2.304 seconds or .791 seconds. I am trying to use std::chrono to do it like this:
auto start_time = std::chrono::system_clock::now();
DoSomeOperation();
std::chrono::duration<double> elapsed_time = std::chrono::system_clock::now() - start_time;
double execution_time = elapsed_time.count();
std::cout << "execution_time = " << execution_time << std::endl;
Following is the output I am getting:
execution_time = 1.9e-05
execution_time = 2.1e-05
execution_time = 1.8e-05
execution_time = 1.7e-05
I am sure that DoSomeOperation only takes a few milliseconds to complete & I need the number in seconds. I need the number in double to use it in a different calculation.
How can I convert this weird 1.9e-05 into a sensible number in double which yields in seconds like .304 or .067 ?
Trying the code from here, I've the same problem.
To change the output format, try std::fixed and std::setprecision
double execution_time = 0.01234;
std::cout << "execution_time = "
<< std::fixed << std::setprecision(3)
<< execution_time << std::endl;
If you have several places where you need to output the execution time, it can be converted to a string and then re-used:
double execution_time = 0.01234;
std::stringstream stream;
stream << std::fixed << std::setprecision(3) << execution_time;
std::string execution_time_as_string = stream.str();
std::cout << "execution_time = " << execution_time_as_string << std::endl;
Use
cout.setf(ios::fixed,ios::floatfield);
cout.precision(3);
cout << MyDouble;
I am trying to find the average UTC time of when a function was called. So I do:
boost::posix_time::ptime current_time_before(boost::posix_time::microsec_clock::universal_time());
DoStuff();
boost::posix_time::ptime current_time_after(boost::posix_time::microsec_clock::universal_time());
How do I go about calculating the averages between these two times?
I tried:
double time_avg = (current_time_before+current_time_after)*0.5;
But I get an error on a linux system that seems to have a problem with "+" but not "-" .
Thank you for your help.
Just... write it naturally?
ptime midpoint(ptime const& a, ptime const& b) {
return a + (b-a)/2; // TODO check for special case `b==a`
}
Live demo:
Live On Coliru
#include <boost/date_time/posix_time/posix_time.hpp>
using boost::posix_time::ptime;
ptime midpoint(ptime const& a, ptime const& b) {
return a + (b-a)/2;
}
int main() {
ptime a = boost::posix_time::second_clock::local_time();
ptime b = a + boost::posix_time::hours(3);
std::cout << "Mid of " << a << " and " << b << " is " << midpoint(a,b) << "\n";
std::swap(a,b);
std::cout << "Mid of " << a << " and " << b << " is " << midpoint(a,b) << "\n";
}
Prints
Mid of 2016-Sep-15 11:17:10 and 2016-Sep-15 14:17:10 is 2016-Sep-15 12:47:10
Mid of 2016-Sep-15 14:17:10 and 2016-Sep-15 11:17:10 is 2016-Sep-15 12:47:10
How can I get a date in the following format in C++:
2016-04-26T19:50:48Z
#include <chrono>
#include <ctime>
time_t _tm = time(NULL);
struct tm*curtime = localtime(&_tm);
And outputting as asctime(curtime)
The current output is: "Thu Apr 28 16:02:41 2016\n"
Documentation is your friend:
std::time_t t
= std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
std::cout << std::put_time( std::localtime( &t ), "%FT%T%z" );
in my system yields
2016-04-29T02:48:56+0200
Based on #Uri's answer which fixes a few bugs and shows the time in the proper timezone along with the milliseconds in ISO8601 format:
auto now = std::chrono::system_clock::now();
std::time_t time = std::chrono::system_clock::to_time_t(now);
std::tm* now_tm = std::localtime(&time);
long long timestamp = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()).count();
std::cout << std::setfill('0')
<< std::put_time(now_tm, "%FT%H:%M:")
<< std::setw(2) << (timestamp / 1000) % 60 << '.'
<< std::setw(3) << timestamp % 1000
<< std::put_time(now_tm, "%z");
I'm combining the std::localtime which gives me calendar values, with std::chrono functions that gives me the precise methods. Here is my code:
#include <ctime>
#include <chrono>
...
auto now = std::chrono::system_clock::now();
auto now_c = std::chrono::system_clock::to_time_t(now)
auto now_tm = std::localtime(&now_c);
auto now_since_epoch = now.time_since_epoch(); // since 1970
auto now_ms = std::chrono::duration_cast<std::chrono::milliseconds>(now_since_epoch).count();
std::cout << std::setfill('0') <<
std::setw(4) << now_tm->tm_year + 1900 << '-' <<
std::setw(2) << now_tm->tm_mon + 1 << '-' <<
std::setw(2) << now_tm->tm_mday << 'T' <<
std::setw(2) << now_ms % (24*60*60*1000) << ':' <<
std::setw(2) << now_ms % (60*60*1000) << ':' <<
std::setw(2) << now_ms % (60*1000) << '.' <<
std::setw(3) << now_ms % (1000);
Although verbose, it is actually doing less than strftime.
Following code outputs the values in time format, i.e. if it's 1:50pm and 8 seconds, it would output it as 01:50:08
cout << "time remaining: %02d::%02d::%02" << hr << mins << secs;
But what I want to do is (a) convert these ints to char/string (b) and then add the same time format to its corresponding char/string value.
I have already achieved (a), I just want to achieve (b).
e.g.
char currenthour[10] = { 0 }, currentmins[10] = { 0 }, currentsecs[10] = { 0 };
itoa(hr, currenthour, 10);
itoa(mins, currentmins, 10);
itoa(secs, currentsecs, 10);
Now if I output 'currenthour', 'currentmins' and 'currentsecs', it will output the same example time as, 1:50:8, instead of 01:50:08.
Ideas?
If you don't mind the overhead you can use a std::stringstream
#include <sstream>
#include <iomanip>
std::string to_format(const int number) {
std::stringstream ss;
ss << std::setw(2) << std::setfill('0') << number;
return ss.str();
}
As from your comment:
"I assumed, using %02 was a standard c/c++ practice. Am I wrong?"
Yes, you are wrong. Also c/c++ isn't a thing, these are different languages.
C++ std::cout doesn't support printf() like formatting strings. What you need is setw() and setfill():
cout << "time remaining: " << setfill('0')
<< setw(2) << hr << ':' << setw(2) << mins << ':' << setw(2) << secs;
If you want a std::string as result, you can use a std::ostringstream in the same manner:
std::ostringstream oss;
oss << setfill('0')
<< setw(2) << hr << ':' << setw(2) << mins << ':' << setw(2) << secs;
cout << "time remaining: " << oss.str();
Also there's a boost library boost::format available, that resembles the format string/place holder syntax.
As an alternative to IOStreams suggested in other answers, you can also use a safe printf implementation such as the fmt library:
fmt::printf("time remaining: %02d::%02d::%02d", hr, mins, secs);
It supports both printf and Python-like format string syntax where type specifiers can be omitted:
fmt::printf("time remaining: {:02}::{:02}::{:02}", hr, mins, secs);
Disclaimer: I'm the author of fmt.
How can I size the char array for strftime without trial and error? Using mktime, the timestamp size N in the example has to be greater 86, otherwise I get arbitrary dates back.
e.g.
N = 86 : 2013-07-13 02:41
N = 82 : 1979-05-18 13:23
How do I efficiently scale N without prior knowledge of the date? The check >0 does not help.
#include <iostream>
#include <cstring>
#include <ctime>
#define N 86
using namespace std;
int main(void)
{
time_t t;
struct tm ts;
char timestamp[N] ;
ts.tm_min = 41;
ts.tm_hour = 2;
ts.tm_mday = 13;
ts.tm_mon = 7 - 1;
ts.tm_year = 13 - 1900 + 2000;
t = mktime(&ts);
if (strftime(timestamp, sizeof(timestamp)-1, "%Y-%m-%d %H:%M", &ts) > 0)
cout << timestamp;
else {
cerr << "strftime failed." <<endl;
return 1;
}
return 0;
}
From the documentation for strftime:
If the length of the resulting C string, including the terminating null-character, doesn't exceed maxsize, the function returns the total number of characters copied to ptr (not including the terminating null-character). Otherwise, it returns zero, and the contents of the array pointed by ptr are indeterminate.
That means if you don't know the size and can dynamically allocate a string you can do something along the lines of:
int size = N; // Some starting size
char *timestamp = malloc(size);
// Your time stuff
int result = strftime(timestamp, size - 1, "%Y-%m-%d %H:%M", &ts);
// While there isn't enough room to store the result
while (result == 0)
{
free(timestamp); // Free old data
size *= 2; // Double the size (should be more than enough)
timestamp = malloc(size); // Allocate the new size. You can check for failed allocations here as well.
// Retry
result = strftime(timestamp, size - 1, "%Y-%m-%d %H:%M", &ts);
}
std::cout << timestamp;
Because you tagged this as C++, perhaps you might consider the following.
--> Note that there is no struggle with the string size here.
// function to create a timestamp style string
std::string yyDmmDdd_hhCmmGet(time_t tt)
{
std::stringstream ss;
// goal - something like: "%Y-%m-%d %H:%M"
{
struct tm mybdtod; // linux api: my broken down time of day
// the following is a relatively slow function
::localtime_r (&tt, &mybdtod);
// linux api - convert time_t to tm as local time
ss << std::setw(4) << (mybdtod.tm_year+1900)
<< "-"
<< std::setfill('0') << std::setw(2) << mybdtod.tm_mon+1
<< "-"
<< std::setfill('0') << std::setw(2) << mybdtod.tm_mday
<< " ";
ss << std::dec << std::setfill('0') << std::setw(2)
<< mybdtod.tm_hour
<< ":"
<< std::setfill('0') << std::setw(2)
<< mybdtod.tm_min;
}
return(ss.str());
}
int t186(void)
{
struct tm ts; // linux api: time struct
::memset(&ts, 0, sizeof(tm));
ts.tm_min = 41;
ts.tm_hour = 3-1;
ts.tm_mday = 13;
ts.tm_mon = 7 - 1;
ts.tm_year = 13 - 1900 + 2000;
time_t tt = mktime(&ts); // linux api: Convert tm struct to time_t
// format time_t to string
std::string s = yyDmmDdd_hhCmmGet(tt); // timestamp style
std::cout << "\n" << s
<< "\n s.size(): "
<< s.size() << " chars" << std::endl;
// now we know how many chars timestamp needs
// add 1 to size because ?strftime seems to need it?
char timestamp[s.size()+1];
(void)strftime(timestamp, sizeof(timestamp), "%Y-%m-%d %H:%M", &ts);
// linux api: format time_t to string
std::cout << "\n" << timestamp << std::endl;
std::cout << " sizeof(timestamp): "
<< sizeof(timestamp) << " chars" << std::endl;
return(0);
}