in squangle/mysql_client/Row.cpp [223:293]
std::chrono::system_clock::time_point parseDateTime(
folly::StringPiece datetime,
enum_field_types date_type) {
const int TM_YEAR_BASE = 1900;
// Clean struct and set daylight savings to information not available
struct tm time_tm = {0};
time_tm.tm_isdst = -1;
std::string microseconds_str;
int microseconds = 0;
bool parse_succeeded = false;
re2::StringPiece re2_datetime(datetime.data(), datetime.size());
switch (date_type) {
case MYSQL_TYPE_TIMESTAMP:
case MYSQL_TYPE_DATETIME:
static re2::RE2 timestamp_pattern(
"(\\d{4})-(\\d{2})-(\\d{2}) "
"(\\d{2}):(\\d{2}):(\\d{2})(?:\\.(\\d{1,6}))?");
parse_succeeded = re2::RE2::FullMatch(
re2_datetime,
timestamp_pattern,
&time_tm.tm_year,
&time_tm.tm_mon,
&time_tm.tm_mday,
&time_tm.tm_hour,
&time_tm.tm_min,
&time_tm.tm_sec,
µseconds_str);
break;
case MYSQL_TYPE_DATE:
static re2::RE2 date_pattern("(\\d{4})-(\\d{2})-(\\d{2})");
parse_succeeded = re2::RE2::FullMatch(
re2_datetime,
date_pattern,
&time_tm.tm_year,
&time_tm.tm_mon,
&time_tm.tm_mday);
break;
default:
break;
};
if (!parse_succeeded) {
throw std::range_error("Can't parse date");
}
if (!microseconds_str.empty()) {
microseconds_str.resize(6, '0');
microseconds = folly::to<int>(microseconds_str.c_str());
}
if (time_tm.tm_year) {
time_tm.tm_year -= TM_YEAR_BASE;
}
if (time_tm.tm_mon) {
time_tm.tm_mon -= 1;
}
auto t = mktime(&time_tm);
if (t == -1) {
throw std::range_error("Date values are invalid");
}
auto chrono_time = std::chrono::system_clock::from_time_t(t);
chrono_time = chrono_time + std::chrono::microseconds(microseconds);
return chrono_time;
}