Farid Z
Farid Z

Reputation: 1018

Is there a standard date/time class in C++?

Does C++ stl have a standard time class? Or do I have to convert to c-string before writing to a stream. Example, I want to output the current date/time to a string stream:

time_t tm();
ostringstream sout;
sout << tm << ends;

In this case I get the current date/time written out as a number without any formatting. I can use c- runtime function strftime to format tm first, but that seems like it should not be necessary if the stl has a time class that can be instantiated from time_t value

Upvotes: 38

Views: 87180

Answers (8)

Howard Hinnant
Howard Hinnant

Reputation: 218710

Well, it's been a dozen years since this question was asked. And now (in C++20) it finally has a better answer.

Yes, there are several standard date/time classes in C++20 (not just one). Each serves different purposes in a strongly typed system. For example std::chrono::zoned_time represents a pairing of a std::chrono::time_zone and a std::chrono::time_point<system_clock, SomeDuration>, and represents the local time in some geographic area. Here is how you might create and print the local time in your current time zone to the finest sub-second precision your OS allows.

cout << zoned_time{current_zone(), system_clock::now()} << '\n';

If you need the local time somewhere else, that is just as easily obtained:

cout << zoned_time{"Africa/Casablanca", system_clock::now()} << '\n';

Unlike in previous C++ standards, time_points based on system_clock are now guaranteed to represent UTC, neglecting leap seconds (aka Unix Time). So to get the current time in UTC it is simply:

cout << system_clock::now() << '\n';

Though if you really wanted to use a zoned_time instead (for example the code may be generic), this also works:

cout << zoned_time{"UTC", system_clock::now()} << '\n';

See https://en.cppreference.com/w/cpp/chrono for many more standard date/time classes. All of them are thread-safe. And you are no longer limited to seconds precision.

Example:

Let's say you wanted to print out your local time 24 hours ago.

Well the first thing is to decide if you mean 24 physical hours, or you want the same time-of-day yesterday as it is now according to your local clock. These two things are almost always the same. But if you've experienced going onto, or coming off of daylight saving in the last 24 hours, they're different.

C++20 chrono can do both, and it is quite easy either way:

A. This is how you compute exactly 24 physical hours before now:

auto timeNow = system_clock::now();
auto timeYesterday = current_zone()->to_local(timeNow - 24h);
std::cout << "24 hours ago, the local time was " << timeYesterday << '\n';
  • Get the current time UTC.
  • Subtract 24h from the current time.
  • Convert the UTC time to your local time.
  • Print it out.

B. If you instead want the date/time which has the same local time yesterday as the local time is now, that is a very slight adjustment to the above code:

auto timeYesterday = current_zone()->to_local(timeNow) - 24h;
  • Convert to local time prior to doing the subtraction, and then do the arithmetic in local time as opposed to UTC.

As stated before, these two algorithms nearly always give the same result. But every once in a while, and for some time zones, they can give different answers. So it is good to know what you want, and have the flexibility to easily program what you want. And to have the code reflect your decision when other programmers are reading it.

Finally, instead of subtracting 24h, one could also use days{1} or 86'400s, or any other unit which indicates the desired passage of time. The only difference is readability.

Upvotes: 6

O. Simon
O. Simon

Reputation: 11

This thread started with the question for "a time class that can be instanciated from time_t value". I searched for the same and looked at "chrono". Until now I cannot say if there is one object representing the time. There is 'system_clock', 'steady_clock', 'clock_time_conversion', 'zoned_time', ... Well, this was by far too confusing for me and I doubt Farid Z searched for such a complex world of classes. The following example to calculate the date 24 hours after now was given:

    using namespace std::literals; // enables literal suffixes, e.g. 24h, 1ms, 1s.
 
    const std::chrono::time_point<std::chrono::system_clock> now =
        std::chrono::system_clock::now();
 
    const std::time_t t_c = std::chrono::system_clock::to_time_t(now - 24h);
    std::cout << "24 hours ago, the time was "
              << std::put_time(std::localtime(&t_c), "%F %T.\n") << std::flush;

24 hours ago, the time was 2021-02-15 18:28:52.

Is this the solution for a simplified usage of time? I sympathized with 'mkluwe' who stated: "If wrapping (or simply using) these functions [ctime] is sufficient (and quicker) than pulling in boost, go with these. There is nothing wrong with them.". Yes, but where to find a C++ class representing time and wrapping those 'ctime' functions? I did not succeed in finding such a class. Therefore I took some time to do so and maybe someone is happy finding it now. The class is named 'cTime' in the namespace 'LibCpp'.

using namespace LibCpp;

cTime timeNow = cTime::now();
stDuration duration24 = stDuration_Ini;
duration24.hours = 24;
cTime duration = cTime::set(duration24);
cTime timeTomorrow = timeNow + duration;
printf("24 hours ago, the time was %s", timeTomorrow.toString().c_str());

See https://github.com/OlafSimon/cTime in case of interest in this class 'cTime' representing Unix time and wrapping 'ctime' functions. And yes, you can instanciate from a 'time_t' variable e.g. named 'myTimeT'.

cTime myTime = cTime::set(myTimeT);

Upvotes: 0

mkluwe
mkluwe

Reputation: 4061

EDIT

The standard "datetime" class is std::chrono::time_point since C++11. The code in the question should be roughly equivalent to

const auto now = std::chrono::system_clock::now();
const auto t_c = std::chrono::system_clock::to_time_t(now);
std::cout << std::put_time(std::localtime(&t_c), "%F %T.\n");

OLD ANSWER

Nitpicking: The STL being the Standard Template Library deals with generic container and algorithms etc. and is unlikely to incorporate classes for date handling and calculation even in the future…

The C++ Standard Library itself includes the STL and a previous version of the C standard library. The latter offers some date and time related functions via #include <ctime> which has already been mentioned above.

If wrapping (or simply using) these functions is sufficient (and quicker) than pulling in boost, go with these. There is nothing wrong with them.

Upvotes: 22

user2827968
user2827968

Reputation:

C++ now has the chrono libraries for date and time. This is documented on http://en.cppreference.com/w/cpp/chrono and http://www.cplusplus.com/reference/chrono/

Upvotes: 10

jdehaan
jdehaan

Reputation: 19928

Not part of STL but well known library is boost.

I would go the way of using boost::date. Here are some examples: http://www.boost.org/doc/libs/1_55_0/doc/html/date_time/date_time_io.html#date_time.io_tutorial.

If you did not try out boost yet I encourage you to do so as it saves you from a lot of nasty issues, as it masks most OS dependent things like threading for example. Many things in boost are header only (template libraries). However datetime requires a lib or dll.

Upvotes: 26

zahir
zahir

Reputation: 1432

There are get_time and put_time in <iomanip> header (i guess these came with C++11) which effectively does string formatting or parsing jobs.

Upvotes: 6

Farid Z
Farid Z

Reputation: 1018

OK. Here is closest I have found about directly writing time to a stream:

time_t t(time(NULL));   // current time
tm tm(*localtime(&t));  

std::locale loc("");    // current user locale
ostringstream sout;
const std::time_put<TCHAR> &tput =
    std::use_facet<std::time_put<TCHAR> >(loc);
tput.put(sout.rdbuf(), sout, _T('\0'), &tm, _T('x'));
sout << ends;

CString sTest(sout.str().c_str());

A very helpful guide is the Apache C++ Standard Library Reference Guide http://stdcxx.apache.org/doc/stdlibref/time-put.html#sec13

Upvotes: 4

bua
bua

Reputation: 4870

There is also a ctime(&time_t) method which outputs string (char*).

Upvotes: 4

Related Questions