- struct tm t;
- auto const &posix = std::locale("C.UTF-8");
- auto const parse_time = [&](char const * const s, bool const has_timezone) {
- std::istringstream ss(str);
- ss.imbue(posix);
- ss >> std::get_time(&t, s);
- if (has_timezone && ss.fail() == false)
- {
- std::string timezone;
- ss >> timezone;
- if (timezone.empty())
+ unsigned short day = 0;
+ signed int year = 0; // yes, Y23K problem – we gonna worry then…
+ std::string weekday, month, datespec, timespec, zone;
+ std::istringstream ss(str);
+ auto const &posix = std::locale::classic();
+ ss.imbue(posix);
+ ss >> weekday;
+ // we only superficially check weekday, mostly to avoid accepting localized
+ // weekdays here and take only its length to decide which datetime format we
+ // encounter here. The date isn't stored.
+ std::transform(weekday.begin(), weekday.end(), weekday.begin(), ::tolower);
+ std::array<char const * const, 7> c_weekdays = {{ "sun", "mon", "tue", "wed", "thu", "fri", "sat" }};
+ if (std::find(c_weekdays.begin(), c_weekdays.end(), weekday.substr(0,3)) == c_weekdays.end())
+ return false;
+
+ switch (weekday.length())
+ {
+ case 4:
+ // Sun, 06 Nov 1994 08:49:37 GMT ; RFC 822, updated by RFC 1123
+ if (weekday[3] != ',')
+ return false;
+ ss >> day >> month >> year >> timespec >> zone;
+ break;
+ case 3:
+ // Sun Nov 6 08:49:37 1994 ; ANSI C's asctime() format
+ ss >> month >> day >> timespec >> year;
+ zone = "UTC";
+ break;
+ case 0:
+ case 1:
+ case 2:
+ return false;
+ default:
+ // Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036
+ if (weekday[weekday.length() - 1] != ',')
+ return false;
+ ss >> datespec >> timespec >> zone;
+ auto const expldate = VectorizeString(datespec, '-');
+ if (expldate.size() != 3)
+ return false;
+ try {
+ size_t pos;
+ day = std::stoi(expldate[0], &pos);
+ if (pos != expldate[0].length())