1
\$\begingroup\$

New to C++ here, by combining different pieces of code I've found, i came with this solution below to convert a date in string to a date object. It works as I want but I'm not certain to do the simplest thing.

#include <iostream>
#include <iomanip>
#include <sstream>
#include <chrono>
#include <ctime>



int main(void)
{
    std::wstring date_time_format = L"%m/%d/%Y";
    std::wistringstream ss{ L"4/28/2022" };
    std::tm dt;

    ss >> std::get_time(&dt, date_time_format.c_str());

    std::time_t final_time;

    final_time = std::mktime(&dt);
    std::tm *ltm = localtime(&final_time);

    std::cout << "Year:" << 1900 + ltm->tm_year<<std::endl;
    std::cout << "Month: "<< 1 + ltm->tm_mon<< std::endl;
    std::cout << "Day: "<< ltm->tm_mday << std::endl;
}
\$\endgroup\$

1 Answer 1

3
\$\begingroup\$

Unnecessary use of wide strings

In your example, there is no need to use wide strings for date_time_format and ss. Just use std::string and std::istringstream and drop the L prefix for the string literals.

Missing std::

You are using localtime() without std:: in front. If you include the C++ versions of the C header files, then there is no guarantee that the C functions will be available in the global namespace.

Use '\n' instead of std::endl

Prefer using '\n' instead of std::endl; the latter is equivalent to the former, but also forces the output to be flushed, which is usually not necessary and has a negative impact on performance.

Missing error checking

If you are trying to parse strings you don't have full control over, the parsing might fail. You should check that ss is still in a good state after trying to parse the date.

Consider using C++20

If you are stuck with C++17 or earlier, then the code you wrote is the only standards compliant way to parse time. However, the situation has improved in C++20 with the introduction of std::chrono::parse() and other calendar features. If you are lucky and your compiler and standard library support it already, you can write:

#include <iostream>
#include <sstream>
#include <chrono>

int main()
{
    std::string date_time_format = "%m/%d/%Y";
    std::istringstream ss{ "4/28/2022" };
    std::chrono::year_month_day date;

    ss >> std::chrono::parse(date_time_format, date);

    if (!ss) {
        /* failed to parse date */
        ...
    }

    std::cout << "Year: "  << date.year()  << '\n';
    std::cout << "Month: " << date.month() << '\n';
    std::cout << "Day: "   << date.day()   << '\n';
}
\$\endgroup\$
2
  • \$\begingroup\$ Perfect, thanks for your feedback. For the C++20 code, i tried to changed from 17 to 20 but didnt succeed to make it work on my computer, i need to update clang but i'm stuck there \$\endgroup\$
    – TmSmth
    Jun 25 at 9:59
  • 1
    \$\begingroup\$ The issue is not so much in the compiler, but in the standard libraries lagging a bit behind. However, there are external libraries that implement the missing C++20 functionality, for example for std::chrono::parse() you can use Howard Hinnant's date library. \$\endgroup\$
    – G. Sliepen
    Jun 25 at 10:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.