How to parse datetime in C++ to std::chrono::time_point, trying different formats until success

The following function will try to parse a given string using std::get_time() , trying out a std::vector of different datetime formats until one succeeds.

It will only consider a parsing a success if the entire string has been consumed. Note that this does not mean that the entire pattern has been matched, just that every character of the string has been consumed by the given pattern.

#include <ctime>
#include <iomanip>
#include <sstream>
#include <vector>

 * Parses a string representing a date and time using a list of possible formats,
 * and returns a time point representing that date and time in the system clock's time zone.
 * @param time_str The string to parse.
 * @param formats A vector of possible formats for the string.
 * @return A time point representing the parsed date and time in the system clock's time zone.
 * @throws DatetimeParseFailure if the string cannot be parsed using any of the provided formats.
std::chrono::time_point<std::chrono::system_clock> ParseTimePoint(const std::string& time_str, const std::vector<std::string>& formats) {
    for (const auto& format : formats) {
        std::tm t = {};
        std::istringstream ss(time_str);
        ss >> std::get_time(&t, format.c_str());
        // Only succeed if the entire string was consumed
        if (! && ss.eof()) {
            std::time_t timet = timegm(&t);
            return std::chrono::system_clock::from_time_t(timet);
    throw DatetimeParseFailure("Failed to parse time string");

It can be used, for example, with one of the following lists of formats:

const std::vector<std::string> datetimeFormats = {
    "%Y-%m-%d %H:%M:%S",
    "%Y/%m/%d %H:%M:%S",
    "%Y%m%d %H:%M:%S",


const std::vector<std::string> dateFormats = {