Outputting Date and Time in C++ using std::chrono
The <chrono>
library only deals with time and not dates, except for the system_clock
which has the ability to convert its timepoints to time_t
. So using <chrono>
for dates will not improve things much. Hopefully we get something like chrono::date
in the not too distant future.
That said, you can use <chrono>
in the following way:
#include <chrono> // chrono::system_clock
#include <ctime> // localtime
#include <sstream> // stringstream
#include <iomanip> // put_time
#include <string> // string
std::string return_current_time_and_date()
{
auto now = std::chrono::system_clock::now();
auto in_time_t = std::chrono::system_clock::to_time_t(now);
std::stringstream ss;
ss << std::put_time(std::localtime(&in_time_t), "%Y-%m-%d %X");
return ss.str();
}
Note that std::localtime
may cause data races. localtime_r
or similar functions may be available on your platforms.
Update:
Using a new version of Howard Hinnant's date library you can write:
#include "date.h"
#include <chrono>
#include <string>
#include <sstream>
std::string return_current_time_and_date() {
auto now = std::chrono::system_clock::now();
auto today = date::floor<days>(now);
std::stringstream ss;
ss << today << ' ' << date::make_time(now - today) << " UTC";
return ss.str();
}
This will print out something like "2015-07-24 05:15:34.043473124 UTC".
On an unrelated note, returning const
objects has become undesirable with C++11; const return values cannot be moved from. I also removed the trailing const because trailing const is only valid for member functions and this function has no need to be a member.
A class for date and time representation in C++11
Since I cannot use C++20 I ended up with this C++11 minimal std::chrono
based implementation:
utctime.h
#include <chrono>
#include <string>
struct UTCClock
{
typedef std::chrono::microseconds duration;
typedef duration::rep rep;
typedef duration::period period;
typedef std::chrono::time_point<UTCClock, duration> time_point;
static const bool is_steady = true;
//
// every time_point will be generated from here
//
static time_point fromDate(int year= 0, int month= 0, int day= 0,
int hour= 0, int min = 0, int sec= 0,
int usec= 0);
//
// convert time_point to a date/time representation
//
static void toDate(const time_point &tp,
int &year, int &month, int &day,
int &hour, int &min, int &sec,
int &usec);
// NOT Supported, we don't need current time. We only
// want to represent UTC DateTime
// static time_point now();
};
using UTCTime = std::chrono::time_point<UTCClock, std::chrono::microseconds>;
utctime.cpp
#include "utctime.h"
#include <ctime>
namespace chrono = std::chrono;
using chrono::duration_cast;
using chrono::time_point_cast;
namespace {
std::time_t to_time_t(const UTCClock::time_point &tp) noexcept
{
return std::time_t(
duration_cast<chrono::seconds>(tp.time_since_epoch()).count());
}
UTCClock::time_point from_time_t(std::time_t tt) noexcept
{
return time_point_cast<UTCClock::duration>(
chrono::time_point<UTCClock,chrono::seconds>(chrono::seconds(tt)));
}
} // namespace
UTCClock::time_point UTCClock::fromDate(
int year, int month, int day, int hour, int min, int sec, int usec)
{
std::tm tm = {0};
tm.tm_year = year - 1900;
tm.tm_mon = month - 1;
tm.tm_mday = day;
tm.tm_hour = hour;
tm.tm_min = min;
tm.tm_sec = sec;
tm.tm_isdst = -1;
std::time_t tt = timegm(&tm);
return from_time_t(tt) + chrono::microseconds(usec);
}
void UTCClock::toDate(const UTCClock::time_point &tp,
int &year,
int &month,
int &day,
int &hour,
int &min,
int &sec,
int &usec)
{
std::time_t tt = to_time_t(tp);
std::tm tm;
gmtime_r(&tt, &tm);
year = tm.tm_year + 1900;
month = tm.tm_mon + 1;
day = tm.tm_mday;
hour = tm.tm_hour;
min = tm.tm_min;
chrono::microseconds leftover =
tp - from_time_t(tt) + chrono::seconds(tm.tm_sec);
sec = duration_cast<chrono::seconds>(leftover).count();
usec = (leftover-chrono::seconds(sec)).count();
}
It can be used like this:
#include "utctime.h"
#include <iostream>
using namespace std::chrono;
int main(int argc, char* argv[])
{
//
// use UTCClock::fromDate to generate a UTCTime
//
UTCTime t1 = UTCClock::fromDate(1901, 1, 1, 0, 0, 0, 0);
UTCTime t2 = UTCClock::fromDate(1901, 1, 1, 1, 0, 0, 0);
//
// Then we can make use of std::chrono algebra like
// subtracting time_point
//
microseconds timeDiff = t2 -t1;
std::cout << "t2-t1 difference in microseconds " <<
timeDiff.count() << std::endl;
std::cout << "t2-t1 difference in hours " <<
duration_cast<hours>(timeDiff).count() << std::endl;
//
// ...or adding/subtracting a duration to a time_point
//
UTCTime t3 = t1 - minutes{3};
std::cout << "t3-t1 difference in minutes " <<
duration_cast<minutes>(t3-t1).count() << std::endl;
t3 = t1 + milliseconds{123};
std::cout << "t3-t1 difference in milliseconds " <<
duration_cast<milliseconds>(t3-t1).count() << std::endl;
//
// ...we can also compare time_points
//
if ( t3 > t1 ) std::cout << "t3 is greater than t1" << std::endl;
//
// We can get a date/time back from a time_point with UTCClock::toDate
//
int year, month, day, hour, min, sec, usec;
UTCClock::toDate(t3, year, month, day, hour, min, sec, usec);
//
// std::chrono is also type safe and doesn't allow to
// mix dates generated by different clocks
//
system_clock::time_point systp = system_clock::now();
// NO: doesn't compile
// auto tx = t1 - systp;
// NO: doesn't compile
// if (t1 < systp);
// NO: doesn't compile
// UTCClock::toDate(systp, year, month, day, hour, min, sec, usec);
return 0;
}
Output:
t2-t1 difference in microseconds 3600000000
t2-t1 difference in hours 1
t3-t1 difference in minutes -3
t3-t1 difference in milliseconds 123
t3 is greater than t1
How to get current time and date in C++?
Since C++ 11 you can use std::chrono::system_clock::now()
Example (copied from en.cppreference.com):
#include <iostream>
#include <chrono>
#include <ctime>
int main()
{
auto start = std::chrono::system_clock::now();
// Some computation here
auto end = std::chrono::system_clock::now();
std::chrono::duration<double> elapsed_seconds = end-start;
std::time_t end_time = std::chrono::system_clock::to_time_t(end);
std::cout << "finished computation at " << std::ctime(&end_time)
<< "elapsed time: " << elapsed_seconds.count() << "s"
<< std::endl;
}
This should print something like this:
finished computation at Mon Oct 2 00:59:08 2017
elapsed time: 1.88232s
How can I input a set start and end time using Chrono or ctime libaray
The std::tm*
returned from std::localtime
is not a good place to store data in. Note that all the different offsets in the std::tm
struct are well documented.
Using only year, month and weekday as you do isn't really enough. There are more than one day in each month having a Saturday for example.
You can do like this:
#include <chrono>
#include <ctime>
#include <iomanip>
#include <iostream>
int main() {
std::tm now{}; // declare and initialize your own tm
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;
// compensate for offsets
now.tm_year -= 1900;
now.tm_mon -= 1;
// convert to std::time_t
std::time_t n = std::mktime(&now);
// here you get a chrono time_point from the user input
cc = std::chrono::system_clock::from_time_t(n);
// convert back to std::time_t
n = std::chrono::system_clock::to_time_t(cc);
// print the result
std::cout << std::put_time(std::localtime(&n), "%FT%T") << "\n";
}
Example input/output:
enter
year month day
2019 11 20
2019-11-20T00:00:00
How to convert std::chrono::time_point to calendar datetime string with fractional seconds?
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
Output time and date with fractional time without using C++11
Using localtime and this post Getting current time with milliseconds:
#include <time.h>
#include <cstdio> // handle type conversions
#include <sys/time.h>
int main (void) {
timeval curTime;
gettimeofday(&curTime, NULL);
int milli = curTime.tv_usec / 1000;
char buffer [80];
strftime(buffer, 80, "%Y-%m-%d %H:%M:%S", localtime(&curTime.tv_sec));
char currentTime[84] = "";
sprintf(currentTime, "%s.%d", buffer, milli);
printf("current date time: %s \n", currentTime);
return 0;
}
outputs:
current date time: 2018-01-28 14:45:52.486
Creating a `std::chrono::time_point` from a calendar date known at compile time
Yes, you can do the entire computation at compile time, creating a constexpr system_clock::time_point
using Howard Hinnant's date/time library.
#include "date/date.h"
#include <chrono>
int
main()
{
using namespace date;
using namespace std::chrono;
constexpr system_clock::time_point tp = sys_days{January/9/2014} + 12h + 35min + 34s;
static_assert(tp == system_clock::time_point{1389270934s}, "");
}
This is assuming that the date/time is UTC. If it isn't, you will have to manually add/subtract the UTC offset to make it so. As time zone rules are changed at the whim of politicians all the time, there is little hope in making them constexpr
. Even historical time zone rules are updated when misunderstandings come to light.
Also this program will port to C++20 by dropping #include "date/date.h"
and using namespace date;
. Also using Howard Hinnant's date/time library requires C++14 constexpr
muscle. C++11 constexpr
is not sufficient (but you can do it at run-time, dropping the constexpr
and static_assert
).
How to convert std::chrono::time_point to string
Howard Hinnant's free, open source, header-only, portable date/time library is a modern way to do this that doesn't traffic through the old C API, and doesn't require that you discard all of your sub-second information. This library is also being proposed for standardization.
There is a lot of flexibility in formatting. The easiest way is to just stream out:
#include "date.h"
#include <iostream>
int
main()
{
using namespace date;
std::cout << std::chrono::system_clock::now() << '\n';
}
This just output for me:
2017-09-15 13:11:34.356648
The using namespace date;
is required in order to find the streaming operator for the system_clock::time_point
(it isn't legal for my lib to insert it into namespace std::chrono
). No information is lost in this format: the full precision of your system_clock::time_point
will be output (microseconds
where I ran this on macOS).
The full suite of strftime
-like formatting flags is available for other formats, with minor extensions to handle things like fractional seconds. Here is another example that outputs with millisecond precision:
#include "date.h"
#include <iostream>
int
main()
{
using namespace date;
using namespace std::chrono;
std::cout << format("%D %T %Z\n", floor<milliseconds>(system_clock::now()));
}
which just output for me:
09/15/17 13:17:40.466 UTC
C++ Errors involving outputting chrono duration
In C++11/14/17, there is no streaming operator for chrono::duration
types. You have two choices:
- Extract the
.count()
:
|
os << right.eR[i].duration.count() << "s ";
- Use this open-source, header-only date/time library:
|
#include "date/date.h"
// ...
using date::operator<<;
os << right.eR[i].duration << " ";
The above datelib is now part of C++20, but is not yet shipping. Vendors are working on it. When you port to it, you can just drop the #include "date/date.h"
and using date::operator<<;
.
Outputting date in ISO 8601 format
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
Related Topics
Why Is the New Random Library Better Than Std::Rand()
C++ Header Files, Code Separation
Vector Push_Back Calling Copy_Constructor More Than Once
Call to Pure Virtual Function from Base Class Constructor
Std::Vector, Thread-Safety, Multi-Threading
Why Does Std::Cout Convert Volatile Pointers to Bool
Why Doesn't Narrowing Conversion Used with Curly-Brace-Delimited Initializer Cause an Error
Sendinput() Not Equal to Pressing Key Manually on Keyboard in C++
Convert Std::Bind to Function Pointer
Error Lnk2005: Already Defined - C++
Using Sizeof on Arrays Passed as Parameters
C++ Array Assignment of Multiple Values
Void Pointers: Difference Between C and C++