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

8

38

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

Gradatim answered 30/10, 2009 at 16:2 Comment(2)
There is now a proposal for a full and modern C++ date/time/timezone before the committee: open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0355r1.html . This proposal is based on this github repository: github.com/HowardHinnant/date which has a full implementation, full documentation, and an active user community.Costmary
The library mentioned in the comment above this one is now part of the draft C++20 specification.Costmary
J
26

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.

Jerriejerrilee answered 30/10, 2009 at 16:12 Comment(0)
R
22

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.

Rattly answered 30/10, 2009 at 16:51 Comment(3)
This answer didn't age well..Towel
@Towel Well, yes... This is old.Rattly
As of 2020 and C++20, the better answer is the comment by Howard Hinnant, and explained in open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0355r1.htmlPhlegm
S
10

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/

Skullcap answered 26/5, 2018 at 12:33 Comment(0)
F
6

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.

Funke answered 13/8, 2012 at 6:32 Comment(0)
C
5

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.

Costmary answered 3/1, 2022 at 0:57 Comment(2)
Regarding first variant, cl.exe gives me error C2679: binary '<<': no operator found which takes a right-hand operand of type 'std::chrono::zoned_time<std::chrono:: duration<std::chrono::system_clock::rep,std::chrono::system_clock::period>,const std::chrono::time_zone *>' (or there is no acceptable conversion)Fortaleza
That looks like a MSVC compiler error message. You will need a V19 and the option: /std:c++latest. Demo: gcc.godbolt.org/z/8efx6dqrrCostmary
C
4

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

Closet answered 30/10, 2009 at 16:7 Comment(1)
Which isn't exactly helpful unless you need exactly that date/time format. Looking at it is only makes me shiver, though; I don't think I'd ever want to see that in an application.Renfro
G
4

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

Gradatim answered 30/10, 2009 at 19:49 Comment(0)
G
0

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);
Gawlas answered 24/9, 2023 at 18:12 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.