16

What is the state of the art way to get date and time as string in c++11?

I know about std::put_time, but the reference says I shall use it only in streams.

There is std::chrono::system_clock which provides to_time_t returning the time as time_t and lacking the date, doesn't it?

I could use a stringstream like bames53: Outputting Date and Time in C++ using std::chrono but that seems to be a workaround.

2
  • 2
    See en.cppreference.com/w/cpp/chrono/c/strftime. Commented Jan 23, 2016 at 13:01
  • Personally I'd stay away from std::chrono but it's your call. abhishek ratore's answer is a very good one in that regard. Commented Jan 23, 2016 at 14:28

5 Answers 5

20

Using Howard Hinnant's free, open-source header-only datetime library, you can get the current UTC time as a std::string in a single line of code:

std::string s = date::format("%F %T", std::chrono::system_clock::now()); 

I just ran this, and the string contains:

2017-03-30 17:05:13.400455 

That's right, it even gives you the full precision. If you don't like that format, all of the strftime formatting flags are available. If you want your local time, there is a timezone library also available, though it is not header only.

std::string s = date::format("%F %T %Z", date::make_zoned(date::current_zone(), std::chrono::system_clock::now())); 

Output:

2017-03-30 13:05:13.400455 EDT 

Update for C++20

This can now be done with the std::lib headers <chrono> and <format>:

#include <chrono> #include <format> #include <string> int main() { std::string s1 = std::format("{:%F %T}", std::chrono::system_clock::now()); std::string s2 = std::format("{:%F %T %Z}", std::chrono::zoned_time{std::chrono::current_zone(), std::chrono::system_clock::now()}); } 

Demo.

Sign up to request clarification or add additional context in comments.

7 Comments

Yes, date.h is 100% thread safe. It does not use the underlying thread-unsafe C API, nor does it rely on thread-unsafe practices such as setting environment variables. The time zone library is also thread safe, including the initialization of the timezone library upon first use (which depends on C++11 thread safe function local statics).
The only part that relies on user-supplied synchronization is the rarely used feature of re-loading the timezone database after first use (which one might use after the application has been running for months). And this characteristic is fully documented: howardhinnant.github.io/date/tz.html#database
Thank you for this great library Howard. I was able to replace 7 lines using the unsafe and clunky strftime() into 1 line! Please propose to the Standard Committee (if you haven't already).
Thanks @Ricky65! You can find the current standardization process of this library near the bottom of the README here: github.com/HowardHinnant/date
The C API won't do sub-second precision. std::chrono will. The C API has two time zones: UTC and local. std::chrono has those two plus all the IANA time zones. The C API doesn't specify whether or not leap seconds are counted, and in practice never does (tracks Unix Time). std::chrono will let you compute both in Unix Time and in true UTC with leap seconds. std::chrono makes it trivial to compute the 3rd Thu of May this year. Not so in the C API. Etc., etc.
|
9

Simpler:

string CurrentDate() { std::time_t now = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()); char buf[100] = {0}; std::strftime(buf, sizeof(buf), "%Y-%m-%d", std::localtime(&now)); return buf; } 

Adjust the format as appropriate for the time too.

Note that I suspect this will not work well for multithreaded code since std::localtime() returns a pointer to an internal struct.

Comments

6

Firstly, std::time_t indeed captures both date and time, since it generally represents seconds from January 1st, 1970.

There is no great support for handling dates in C++11. You still have to depend on boost if you don't wish to do it, mostly, manually. Here's how to do it manually.

You can use it—in a thread-safe way—together with any std::chrono::*clock, such as std::system_clock, like this:

std::string get_date_string(std::chrono::time_point t) { auto as_time_t = std::chrono::system_clock::to_time_t(t); struct tm tm; if (::gmtime_r(&as_time_t, &tm)) if (std::strftime(some_buffer, sizeof(some_buffer), "%F", &tm)) return std::string{some_buffer}; throw std::runtime_error("Failed to get current date as string"); } 

Somewhere else, you can issue:

get_date_string(std::system_clock::now()); 

The relatively good thing about this solution is that, at the API level, you're still using modern, portable C++ concepts such as std::chrono::time_point, and of course, std::string.

1 Comment

Nice. You might want to use std::chrono::system_clock::time_point for the function argument. The buffer some_buffer is char array (e.g. char some_buffer[64];) that must be declared inside the function and must not be static (otherwise the whole thread safety is lost). You could reuse the std::string internal buffer for that (resize, then contract) and avoid copying.
4

timestamp like this;

#include <iostream> #include <chrono> #include <ctime> int main() { std::chrono::time_point<std::chrono::system_clock> now = std::chrono::system_clock::now(); std::time_t start_time = std::chrono::system_clock::to_time_t(now); char timedisplay[100]; struct tm buf; errno_t err = localtime_s(&buf, &start_time); if (std::strftime(timedisplay, sizeof(timedisplay), "%H:%M:%S", &buf)) { std::cout << timedisplay << '\n'; } } 

Date in a similar manner.

Comments

3

You can use the code snippet given below as it will serve your purpose. Here use time.h header file for required localtime() function and then using the strftime() function with required parameters will give the output and it returns it as a string.

#include <iostream> #include <string> #include <time.h> std::string current_date(); std::string current_time(); int main(){ std::cout<<"Current date => "<<current_date()<<"\n"; std::cout<<"Current time => "<<current_time()<<"\n"; } std::string current_date(){ time_t now = time(NULL); struct tm tstruct; char buf[40]; tstruct = *localtime(&now); //format: day DD-MM-YYYY strftime(buf, sizeof(buf), "%A %d/%m/%Y", &tstruct); return buf; } std::string current_time(){ time_t now = time(NULL); struct tm tstruct; char buf[40]; tstruct = *localtime(&now); //format: HH:mm:ss strftime(buf, sizeof(buf), "%X", &tstruct); return buf; } 

1 Comment

Since std::string is returned, temporal std::string buf is a better option. That would remove an extra overhead for constructing string from a char buffer. In provided example return buf == std::string(buf), which invoke memcpy to copy 'buf' into newly created return sting. After all: std::string buf; buf.resize(40); ... strftime((char*)buf.data(), 40, "%A %d/%m/%Y", &tstruct);

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.