10

I fully expect this to be closed within a day or two since it's a kinda subjective topic, but here goes anyway: Why does it take at least 5 lines of code to get the date/time in C++?

This was one of the first things I learnt how to do in C, but that was a long time ago...and I remember it taking me a while to grasp the whole concept back then. Now I'm much more experienced, but after having gotten used to higher-level languages like C# and Java, it really irritates me that something this simple requires all of this:

#include <iostream>
#include <chrono>
#include <ctime>

using namespace std::chrono;

// First get an epoch value
auto time = system_clock::to_time_t(system_clock::now());

// Now we need a char buffer to hold the output
char timeString[20] = "";

// Oh and a tm struct too! Gotta have that, just to make it more complicated!
tm tmStruct;

// Oh and BTW, you can't just get your local time directly;
// you need to call localtime_s with the tm AND the time_t!
// Can't use localtime anymore since it's "unsafe"
localtime_s(&tmStruct, &time);

// Hurray! We finally have a readable string!!
strftime(timeString, 20, "%d-%m-%Y %T", &tmp);

cout << timeString << "Phew! I'm tired, I guess the time must be bedtime!"

Now compare that to C# (for example):

Console.WriteLine(DateTime.Now.ToString("%d-%m-%Y %T")); // Well that was easy!

Is there a good reason for this nonsense, or does it just boil down to the general idea that C++ is for low-level stuff where the dev wants/needs more control?

As an avid code golfer, I'll take the second option over the first any day of the week, since shorter code is generally cleaner, more readable, easier to debug and just generally better IMHO. So is there a shorter method in C++ that I'm missing? MTIA!

curiousguy
  • 8,038
  • 2
  • 40
  • 58
Kenny83
  • 769
  • 12
  • 38
  • 4
    Because local time except for display purposes is almost completely useless. It's affected by the clocks going forward / back and timezone changes. – Richard Critten Dec 28 '19 at 10:26
  • 2
    What you are using is the C method, which pretty much *has* to be convoluted from a C++ perspective. – L. F. Dec 28 '19 at 10:30
  • @LF That's exactly what I was expecting; that a higher-level approach would be possible in C++. But apparently not according to my research...please enlighten me! – Kenny83 Dec 28 '19 at 10:32
  • @RichardCritten Fair point, +1 for you sir :-) – Kenny83 Dec 28 '19 at 10:33
  • 2
    The core philosophy of `C` (and then `C++`) was for the language to do as little as possible and to let third parties write libraries to make more specific tasks easier. I am sure you can find libraries to make it simpler. – Galik Dec 28 '19 at 10:34
  • 1
    That might seem a bit convoluted but is is a design decision. The real problem is that localtime_s isn't thread safe at all. In my opinion that the real design fault with local time handling. – Gustavo Dec 28 '19 at 10:35
  • 1
    `localtime_s` isn't a problem of C++, [it's a problem of MSVC](https://stackoverflow.com/questions/50724726/why-didnt-gcc-implement-s-functions). Probably another silly attempt of M$ to break code compatibility among other compilers. – tripulse Nov 25 '20 at 13:53

1 Answers1

12

All of the tm stuff is inherited from C. C code work with functions with output parameters and return codes, so the code tends to be convoluted. Let's just take file I/O as an example:

FILE *file;
file = fopen("foo", "w");
fprintf(file, "%d", /* some number */);
fclose(file);

vs

std::ofstream ofs{"foo"};
ofs << /* some number */;

In this case, the C++ standard library just doesn't happen to contain the date functionalities, which is a shame ...


... until C++20, where Howard Hinnant's date library is voted into the standard library! The library is pretty lightweight, so don't wait until C++20 to try it out! Here's the example in the README file:

#include "date.h"
#include <iostream>

int
main()
{
    using namespace date;
    using namespace std::chrono;
    auto now = system_clock::now();
    std::cout << "The current time is " << now << " UTC\n";
    auto current_year = year_month_day{floor<days>(now)}.year();
    std::cout << "The current year is " << current_year << '\n';
    auto h = floor<hours>(now) - sys_days{January/1/current_year};
    std::cout << "It has been " << h << " since New Years!\n";
}

(live demo)

L. F.
  • 19,445
  • 8
  • 48
  • 82
  • OMG don't bring back those nightmares of file I/O from 15 years ago! And hurrah for Howard's library! Any idea when C++20 will become widely adopted? I'll definitely download the lib now but would be good to know :-) – Kenny83 Dec 28 '19 at 10:52
  • @Kenny83 Well, C++20 is a massive change, so I'd expect the year to be around 2023 I guess. – L. F. Dec 28 '19 at 11:13
  • LOL I assumed as much. I do understand the reasons why, but the fact that it takes so long for standards to actually be adopted is just one of many reasons why I'll always prefer C# :P Anyway for now I **need** to use C++ for a particular project, so I'll quit whining and say "thank you for the quick and well-formed answers" :D – Kenny83 Dec 28 '19 at 11:29
  • 1
    To be honest the whole FILE api is clearer than whatever fstreams are trying to do, just that they aren't wrapped in some class with nice RAII. – Andrei Damian Dec 28 '19 at 11:52
  • For C++17 and prior, [Boost Date Time](https://www.boost.org/doc/libs/1_72_0/doc/html/date_time.html) may be of interest. (For those who are not Boost adverse.) – Eljay Dec 28 '19 at 14:05
  • [Howard Hinnant's library](https://github.com/HowardHinnant/date) works with your platform back to C++11. It can't go back to C++03 because it is based on `` which was introduced with C++11. – Howard Hinnant Dec 28 '19 at 14:57