43 const static REGEX_NAMESPACE::regex dateRegex{R"(^([0-9]{4})\-([0-9]{2})\-([0-9]{2})$)"};
47 throw std::invalid_argument(value +
" is not a date string according to RFC 3339.");
50 const auto year = std::stoi(matches[1].str());
51 const auto month = std::stoi(matches[2].str());
52 const auto mday = std::stoi(matches[3].str());
54 const auto isLeapYear = (year % 4 == 0) && ((year % 100 != 0) || (year % 400 == 0));
59 }
else if (month <= 7) {
69 const static REGEX_NAMESPACE::regex timeRegex{R"(^([0-9]{2})\:([0-9]{2})\:([0-9]{2})(\.[0-9]+)?(?:[Zz]|((?:\+|\-)[0-9]{2})\:([0-9]{2}))$)"};
73 throw std::invalid_argument(value +
" is not a time string according to RFC 3339.");
76 auto hour = std::stoi(matches[1].str());
77 auto minute = std::stoi(matches[2].str());
78 auto second = std::stoi(matches[3].str());
88 if (!matches[5].str().empty()) {
89 offsetHour = std::stoi(matches[5].str());
90 offsetMinute = std::stoi(matches[6].str());
99
100
101
102
104 auto day_minutes = hour * 60 + minute - (offsetHour * 60 + offsetMinute);
106 day_minutes += 60 * 24;
107 hour = day_minutes % 24;
108 minute = day_minutes / 24;
110 if (hour == 23 && minute == 59)
296 const static std::string scheme{R"(([A-Za-z][A-Za-z0-9+\-.]*):)"};
297 const static std::string hierPart{
298 R"((?:(\/\/)(?:((?:[A-Za-z0-9\-._~!$&'()*+,;=:]|)"
299 R"(%[0-9A-Fa-f]{2})*)@)?((?:\[(?:(?:(?:(?:[0-9A-Fa-f]{1,4}:){6}|)"
300 R"(::(?:[0-9A-Fa-f]{1,4}:){5}|)"
301 R"((?:[0-9A-Fa-f]{1,4})?::(?:[0-9A-Fa-f]{1,4}:){4}|)"
302 R"((?:(?:[0-9A-Fa-f]{1,4}:){0,1}[0-9A-Fa-f]{1,4})?::(?:[0-9A-Fa-f]{1,4}:){3}|)"
303 R"((?:(?:[0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})?::(?:[0-9A-Fa-f]{1,4}:){2}|)"
304 R"((?:(?:[0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})?::[0-9A-Fa-f]{1,4}:|)"
305 R"((?:(?:[0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})?::)(?:[0-9A-Fa-f]{1,4}:[0-9A-Fa-f]{1,4}|)"
306 R"((?:(?:25[0-5]|2[0-4][0-9]|)"
307 R"([01]?[0-9][0-9]?)\.){3}(?:25[0-5]|)"
309 R"([01]?[0-9][0-9]?))|)"
310 R"((?:(?:[0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})?::[0-9A-Fa-f]{1,4}|)"
311 R"((?:(?:[0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})?::)|)"
312 R"([Vv][0-9A-Fa-f]+\.[A-Za-z0-9\-._~!$&'()*+,;=:]+)\]|)"
315 R"([01]?[0-9][0-9]?)\.){3}(?:25[0-5]|)"
317 R"([01]?[0-9][0-9]?)|)"
318 R"((?:[A-Za-z0-9\-._~!$&'()*+,;=]|)"
319 R"(%[0-9A-Fa-f]{2})*))(?::([0-9]*))?((?:\/(?:[A-Za-z0-9\-._~!$&'()*+,;=:@]|)"
320 R"(%[0-9A-Fa-f]{2})*)*)|)"
321 R"(\/((?:(?:[A-Za-z0-9\-._~!$&'()*+,;=:@]|)"
322 R"(%[0-9A-Fa-f]{2})+(?:\/(?:[A-Za-z0-9\-._~!$&'()*+,;=:@]|)"
323 R"(%[0-9A-Fa-f]{2})*)*)?)|)"
324 R"(((?:[A-Za-z0-9\-._~!$&'()*+,;=:@]|)"
325 R"(%[0-9A-Fa-f]{2})+(?:\/(?:[A-Za-z0-9\-._~!$&'()*+,;=:@]|)"
326 R"(%[0-9A-Fa-f]{2})*)*)|))"};
328 const static std::string query{R"((?:\?((?:[A-Za-z0-9\-._~!$&'()*+,;=:@\/?]|%[0-9A-Fa-f]{2})*))?)"};
329 const static std::string fragment{
330 R"((?:\#((?:[A-Za-z0-9\-._~!$&'()*+,;=:@\/?]|%[0-9A-Fa-f]{2})*))?)"};
331 const static std::string uriFormat{scheme + hierPart + query + fragment};
336 throw std::invalid_argument(value +
" is not a URI string according to RFC 3986.");