C++: how to get the actual time with time and localtime? - c++

I'm looking for a way to save the time in a HH::MM::SS fashion in C++. I saw here that they are many solutions and after a little research I opted for time and localtime. However, it seems like the localtime function is a little tricky, since it says:
All calls to localtime and gmtime use the same static structure, so
each call overwrites the results of the previous call.
The problem that this causes is shown in the next snippet of code:
#include <ctime>
#include <iostream>
using namespace std;
int main() {
time_t t1 = time(0); // get time now
struct tm * now = localtime( & t1 );
std::cout << t1 << std::endl;
sleep(2);
time_t t2 = time(0); // get time now
struct tm * now2 = localtime( & t2 );
std::cout << t2 << std::endl;
cout << (now->tm_year + 1900) << '-'
<< (now->tm_mon + 1) << '-'
<< now->tm_mday << ", "
<< now->tm_hour << ":" << now->tm_min << ":" << now->tm_sec
<< endl;
cout << (now2->tm_year + 1900) << '-'
<< (now2->tm_mon + 1) << '-'
<< now2->tm_mday << ", "
<< now2->tm_hour << ":" << now2->tm_min << ":" << now2->tm_sec
<< endl;
}
A typical output for this is:
1320655946
1320655948
2011-11-7, 9:52:28
2011-11-7, 9:52:28
So as you can see, the time_t timestamps are correct, but the localtime messes everything up.
My question is: how do I convert a timestamp ot type time_t into a human-readable time?

If you are worried about reentrancy in localtime and gmtime, there is localtime_r and gmtime_r which can handle multiple calls.
When it comes to formatting the time to your liking, check the function strftime.

the localtime() call stores the results in an internal buffer.
Every time you call it you overwrite the buffer.
An alternative solution would be to make a copy of the buffer.
time_t t1 = time(0); // get time now
struct tm* now = localtime( & t1 ); // convert to local time
struct tm copy = *now; // make a local copy.
// ^^^ notice no star.
But note: The only time you should be converting to local time is when you display the value. At all other times you should just keep the time as UTC (for storage and manipulation). Since you are only converting the objects for display convert then print immediately and then things will not go wrong.

localtime has what is best considered a legacy interface. It can't be
used in multithreaded code, for example. In a multithreaded
environment, you can use localtime_r under Posix or localtime_s
under Windows. Otherwise, all you have to do is save the results:
tm then = *localtime( &t1 );
// ...
tm now = *localtime( &t2 );
It would probably be more idiomatic, however, to only call localtime
immediately before formatting the output, e.g.:
std::string
timestampToString( time_t timeAndDate )
{
char results[100];
if ( strftime( results, sizeof( results ), "%Y-%m-%d, %H:%M:%S",
localtime( &timeAndDate) ) == 0 ) {
assert( 0 );
}
return results;
}
and then writing:
std::cout << formatTime( t1 ) << std::endl;
(You could also create a more generic formatting function, which took
the format as an argument.)

You can run continuous clock using following code. It works nicely.
#include<iostream>
#include <Windows.h>
#include<ctime>
using namespace std;
void main() {
while(true) {
system("cls"); //to clear screen
time_t tim;
time(&tim);
cout << ctime(&tim);
Sleep(1);
}
}

Related

Getting Current Date inside a C++ process running 24*7

I have a backend process running 24*7 mostly built using C++ and I need to validate if an input date (in format YYYYMMDD) belongs in a set of next 5 business days. The input date is not a clear indicator of the current date so I am using the following function to get the current date and then calculating the next 5 business days from it.
const std::string& CurrentDateStr() {
static const std::string sDate = []() {
time_t currTime = time(NULL);
struct tm timeinfo;
localtime_r(&currTime, &timeinfo);
char buffer[16]="";
strftime(buffer, sizeof(buffer), "%Y%m%d", &timeinfo);
return std::string(buffer);
} ();
return sDate;
}
This function returns me the correct current date if the process was started today but if the process continues running till tomorrow then it will return me yesterday's date as current date due to which calculation of next 5 business days from current date goes for a toss.
Is this expected ? Is there some workaround for it or is there a better way to implement the requirement using standard C++
Your issue is the static variable. You should read up on that, because you're going to encounter it a lot. This is what the comments were trying to get you to do. You can fix your issue by just removing it:
const std::string& CurrentDateStr() {
time_t currTime = time(NULL);
struct tm timeinfo;
localtime_r(&currTime, &timeinfo);
char buffer[16]="";
strftime(buffer, sizeof(buffer), "%Y%m%d", &timeinfo);
return std::string(buffer);
}
For a more modern solution, as suggested in the comments as well, read up on chrono. Especially system_clock::now().
one way to do it using chrono:
#include <iostream>
#include <ctime>
#include <chrono>
#include <thread>
int main()
{
while (true)
{
theTime currentTime = time(nullptr);
tm* date = gmtime(&currentTime);
// Print the date and time
std::cout << "Current date and time: " << date->theDay << "/" << date->theMon + 1 << "/" << date->theYear + 1900;
std::cout << " " << date->theHour << ":" << date->theMmin << ":" << date->theSec << std::endl;
// Wait for 1 minute
std::this_thread::sleep_for(std::chrono::minutes(1));
}
}
OR Use the sleep method.
#include <iostream>
#include <ctime>
#include <unistd.h>
int main()
{
while (true)
{
time_t currentTime = time(nullptr);
tm* date = gmtime(&currentTime);
std::cout << "Current date and time: " << date->tm_mday << "/" << date->tm_mon + 1 << "/" << date->tm_year + 1900;
std::cout << " " << date->tm_hour << ":" << date->tm_min << std::endl;
// Wait for 1 minute (60 seconds)
sleep(60);
}
}

How to append system time to a string variable

#include<iostream>
#include<ctime>
#include<string>
using namespace std;
int main()
{
string NowTime;
time_t now;
struct tm nowLocal;
now=time(NULL); // get the time from the OS
nowLocal=*localtime(&now);
NowTime = nowLocal.tm_hour + ':' + nowLocal.tm_min + ':' + nowLocal.tm_sec;
cout<< NowTime;
}
When I run the program, it display nothing, can someone help me? I am totally new in programming.
If you try
cout << nowLocal.tm_hour + ':' + nowLocal.tm_min + ':' + nowLocal.tm_sec;
you'll see an integer, not anything resembling a time.
This is because it's the sum of five integers - the characters are promoted to integers, and then it's all added up.
The simplest fix is to not build a string at all but to output the parts individually:
cout << nowLocal.tm_hour << ':' << nowLocal.tm_min << ':' << nowLocal.tm_sec;
Otherwise, you need to convert those numbers to strings:
NowTime = std::to_string(nowLocal.tm_hour) + ':' + std::to_string(nowLocal.tm_min) + ':' + std::to_string(nowLocal.tm_sec);
or, you can use a std::ostringstream, which works just like std::cout and other streams, but writes to a std::string:
std::ostringstream ss;
ss << nowLocal.tm_hour << ':' << nowLocal.tm_min << ':' << nowLocal.tm_sec;
NowTime = ss.str();
The line:
NowTime = nowLocal.tm_hour + ':' + nowLocal.tm_min + ':' + nowLocal.tm_sec;
is adding the hour, minute, and second to the numeric value of the colon symbol, since char is implicitly coerced to an int. That value is then being interpreted as a char in the string assignment operator.
Instead, you can simply output the values directly to cout. They will be formatted appropriately by cout's stream insertion operator <<.
#include<iostream>
#include<ctime>
#include<string>
using namespace std;
int main()
{
string NowTime;
time_t now;
tm nowLocal;
now=time(NULL); // get the time from the OS
nowLocal=*localtime(&now);
cout << nowLocal.tm_hour << ':' << nowLocal.tm_min << ':' << nowLocal.tm_sec;
return 0;
}
If you would instead want to store them in a string, read up about stringstreams. They have a similar syntax to cout and can make formatting strings much easier.
Instead of having to put the result in a variable, you could output it like this:
cout << nowLocal.tm_hour << ':' << nowLocal.tm_min << ':' << nowLocal.tm_sec;
Live Example
Also, if you want to keep the variable, do this:
NowTime = std::to_string(nowLocal.tm_hour) + ':' + std::to_string(nowLocal.tm_min) + ':' + std::to_string(nowLocal.tm_sec);
cout << NowTime;
Try this:
#include<iostream>
#include<ctime>
#include<string>
#include <sstream>
using namespace std;
int main()
{
string NowTime;
time_t now;
struct tm nowLocal;
now=time(NULL); // get the time from the OS
nowLocal=*localtime(&now);
stringstream s;
s<<nowLocal.tm_hour;
s<<":";
s<<nowLocal.tm_min;
s<<":";
s<<nowLocal.tm_sec;
NowTime = s.str();
cout<< NowTime;
}
You cannot cas directly from int to string and you need put values into stream and then to string.
What about using iostringstream to build the string you want?
#include<iostream>
#include<ctime>
#include<string>
#include <sstream>
using namespace std;
int main()
{
ostringstream NowTime;
time_t now;
struct tm nowLocal;
now=time(NULL); // get the time from the OS
nowLocal=*localtime(&now);
NowTime << nowLocal.tm_hour << ":" << nowLocal.tm_min << ":" << nowLocal.tm_sec;
cout<< NowTime.str() << endl;
}
Or for the purposes of your program you could simple use std::cout which also happens to be an output stream.
cout << nowLocal.tm_hour << ":" << nowLocal.tm_min << ":" << nowLocal.tm_sec << endl;
Since it looks like you're pre-c++11 and can't use std::to_string. Here's a C-like way of doing it, sticking to the includes you're currently using.
#include<iostream>
#include<ctime>
#include<string>
using namespace std;
#define STR_LEN 128
int main()
{
string nowTime;
time_t now;
struct tm nowLocal;
now = time( NULL ); // get the time from the OS
nowLocal = *localtime( &now );
char hour[ STR_LEN ], min[ STR_LEN ], sec[ STR_LEN ];
sprintf( hour, "%d", nowLocal.tm_hour );
sprintf( min, "%d", nowLocal.tm_min );
sprintf( sec, "%d", nowLocal.tm_sec );
nowTime = string( hour ) + ':' + string( min ) + ':' + string( sec );
cout << nowTime << endl;
}
How append system time to a string?
My answer is to build a convenience function.
If you really only need hour, minute, second, then you need not use the relatively slow localtime(). (on the other hand, if you do need more, I think you should prefer localtime_r() for the conversion).
For an embedded system several contracts back, I found this conversion to be a relatively slow function and chose to avoid it. The algorithms to handle leap days, centuries, etc. appear simple enough. I suspect I considered it slow simply because it calculates more than I needed in that application that was trying to do the conversion many times per second.
There exists a simpler (and probably still faster) approach involving modular arithmetic. It starts the same - with a time(0) (and thus I suspect what I am doing here is 'hidden' in the localtime_r() function). Side note 1 - on my older Dell running Ubuntu 15.10, time(0) is simply the fastest access to the wall clock, measuring about 6 or 7 ns 'typical' duration. Side note 2 - time_t may change someday. "The time_t Wikipedia article article sheds some light on this. The bottom line is that the type of time_t is not guaranteed in the C specification."
The code I currently use to conveniently generate a time stamp string:
std::string hhCmmCssGet(time_t tt = 0) // tt has default value
{
time_t now = ( tt ? tt : time(0) );
static time_t prev = 0;
static char hhmmss[] = "hh:mm:ss";
if (prev != now)
{
prev = now;
const int32_t CST = -6;
int64_t hr = ((now / 3600) % 24) + CST; // hr of day, CST offset
if (hr < 0) hr += 24;
uint64_t min = ((now / 60) % 60); // min of day
uint64_t sec = (now % 60); // sec of day
std::stringstream ss;
ss << std::dec
<< std::setfill('0') << std::setw(2) << hr << ":"
<< std::setfill('0') << std::setw(2) << min << ":"
<< std::setfill('0') << std::setw(2) << sec;
for (size_t i=0; i<8; i++) // transfer new value
hhmmss[i] = ss.str()[i]; // into static hhmmss
}
std::string retVal(hhmmss);
return(retVal);
}
The static items and "if (prev != now)" clause, allow this function to be invoked thousands of times per second ... with much reduced effort. The second, after all, only updates 1ce per second. And note that the std::stringstream stuff and modular arithmetic operations only run 1ce per second.

MM:hh:mm time with c ++

So I haven't seen here or anywhere else a way to get only the month hours and minutes using <ctime> or other library.
What I can do now is just get the full current date:
time_t now = time(0);
cout<<ctime(&now);
Any suggestions?
You can use the <ctime> standard library like this:
#include <ctime>
#include <iostream>
int main()
{
// get current time
std::time_t timer = std::time(0);
// convert to 'broken time'
std::tm bt = *std::localtime(&timer); // not thread safe
// extract month number from 'broken time' struct
std::cout << "month: " << (bt.tm_mon + 1) << '\n';
std::cout << "hours: " << (bt.tm_hour) << '\n';
std::cout << "mins : " << (bt.tm_min) << '\n';
}
The function std::localtime returns a pointer to an internal statc structure of type std::tm.
Because it returns a pointer to an internal struct it is best to copy it to a local version by dereferencing the pointer using *:
// copy what the returned pointer points to into `bt`.
std::tm bt = *std::localtime(&timer);
Since you are using ctime (C time), all C things should work. You could use strftime
char timestr[32];
strftime(timestr, sizeof(timestr), "%m:%H:%M", localtime(&now));
If boost is fine for you try this one :
boost::posix_time::to_simple_string(boost::posix_time::microsec_clock::local_time()).c_str()
try
std::put_time("%a %b %d %H:%M:%S %Y", &now);

std::cout shows hex on the screen instead of text

I get system time like this:
time_t t = time(0);
struct tm* now = localtime(&t);
TCHAR* tInfo = new TCHAR[256];
swprintf_s(tInfo
, 256
, _T("Current time: %i:%i:%i")
, now->tm_hour
, now->tm_min
, now->tm_sec);
And then show on screen:
std::cout << tInfo << std::endl;
But insted of Current time: 12:57:56 I got: 0x001967a8 on the screen. What I did wrong ?
You are trying to print a "wide" string. You need to use :
std::wcout << tInfo << std::endl;
The "narrow" version cout doesn't know about "wide" characters, so will just print the address, just like if you tried to print some other random pointer type.
Try:
std::wcout << tInfo << std::endl;
C++ shares its date/time functions with C. The tm structure is probably the easiest for a C++ programmer to work with - the following prints today's date:
#include <ctime>
#include <iostream>
using namespace std;
int main() {
time_t t = time(0); // get time now
struct tm * now = localtime( & t );
cout << (now->tm_year + 1900) << '-'
<< (now->tm_mon + 1) << '-'
<< now->tm_mday
<< endl;
}

Capturing a time in milliseconds

The following piece of code is used to print the time in the logs:
#define PRINTTIME() struct tm * tmptime;
time_t tmpGetTime;
time(&tmpGetTime);
tmptime = localtime(&tmpGetTime);
cout << tmptime->tm_mday << "/" <<tmptime->tm_mon+1 << "/" << 1900+tmptime->tm_year << " " << tmptime->tm_hour << ":" << tmptime->tm_min << ":" << tmptime->tm_sec<<">>";
Is there any way to add milliseconds to this?
To have millisecond precision you have to use system calls specific to your OS.
In Linux you can use
#include <sys/time.h>
timeval tv;
gettimeofday(&tv, 0);
// then convert struct tv to your needed ms precision
timeval has microsecond precision.
In Windows you can use:
#include <Windows.h>
SYSTEMTIME st;
GetSystemTime(&st);
// then convert st to your precision needs
Of course you can use Boost to do that for you :)
//C++11 Style:
cout << "Time in Milliseconds =" <<
chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now().time_since_epoch()).count()
<< std::endl;
cout << "Time in MicroSeconds=" <<
chrono::duration_cast<chrono::microseconds>(chrono::steady_clock::now().time_since_epoch()).count()
<< std::endl;
You need a timer with a higher resolution in order to capture milliseconds. Try this:
int cloc = clock();
//do something that takes a few milliseconds
cout << (clock() - cloc) << endl;
This is of course dependent on your OS.
The high resolution timers are usually gettimeofday on Linux style platforms and QueryPerformanceCounter on Windows.
You should be aware that timing the duration of a single operation (even with a high resolution timer) will not yield accurate results. There are too many random factors at play. To get reliable timing information, you should run the task to be timed in a loop and compute the average task time. For this type of timing, the clock() function should be sufficient.
If you don't want to use any OS-specific code, you can use the ACE package which supplies the ACE_OS::gettimeofday function for most standard operating systems.
For example:
ACE_Time_Value startTime = ACE_OS::gettimeofday();
do_something();
ACE_Time_Value endTime = ACE_OS::gettimeofday();
cout << "Elapsed time: " << (endTime.sec() - startTime.sec()) << " seconds and " << double(endTime.usec() - startTime.usec()) / 1000 << " milliseconds." << endl;
This code will work regardless of your OS (as long as ACE supports this OS).
In Ubuntu 16.04 this worked for me...
const std::string currentDateTime() {
char fmt[64], buf[64];
struct timeval tv;
struct tm *tm;
gettimeofday(&tv, NULL);
tm = localtime(&tv.tv_sec);
strftime(fmt, sizeof fmt, "%Y-%m-%d %H:%M:%S.%%06u", tm);
snprintf(buf, sizeof buf, fmt, tv.tv_usec);
return buf;
}
Then, with...
std::cout << currentDateTime();
I get...
2016-12-29 11:09:55.331008
New answer for old question using C++11 or C++14 and this free, open-source library:
#include "tz.h"
#include <iostream>
int
main()
{
using namespace date;
using namespace std;
using namespace std::chrono;
auto now = make_zoned(current_zone(), floor<milliseconds>(system_clock::now()));
cout << format("%e/%m/%Y %T", now) << '\n';
}
This just output for me:
16/01/2017 15:34:32.167
which is my current local date and time to millisecond precision. By eliminating the floor<milliseconds>() you will automatically get whatever precision your system_clock has.
If you wanted the result as a UTC timestamp instead of a local timestamp, it is even easier:
auto now = floor<milliseconds>(system_clock::now());
cout << format("%e/%m/%Y %T", now) << '\n';
And if you want a UTC timestamp and you aren't picky about the precision or the format, you can just:
cout << system_clock::now() << '\n';
which just output for me:
2017-01-16 20:42:11.267245