23 namespace time_internal {
28 const char kDigits[] =
"0123456789";
30 const char* ParseInt(
const char* p,
int min,
int max,
int* vp) {
33 const int kMaxInt = std::numeric_limits<int>::max();
34 for (;
const char* dp = strchr(kDigits, *p); ++p) {
35 int d =
static_cast<int>(dp - kDigits);
37 if (value > kMaxInt / 10)
return nullptr;
39 if (value > kMaxInt - d)
return nullptr;
42 if (p == op || value < min || value > max)
return nullptr;
48 const char* ParseAbbr(
const char* p, std::string*
abbr) {
52 if (*p ==
'\0')
return nullptr;
54 abbr->assign(op + 1, static_cast<std::size_t>(p - op) - 1);
58 if (strchr(
"-+,", *p))
break;
59 if (strchr(kDigits, *p))
break;
62 if (p - op < 3)
return nullptr;
63 abbr->assign(op, static_cast<std::size_t>(p - op));
68 const char* ParseOffset(
const char* p,
int min_hour,
int max_hour,
int sign,
69 std::int_fast32_t* offset) {
70 if (p ==
nullptr)
return nullptr;
71 if (*p ==
'+' || *p ==
'-') {
72 if (*p++ ==
'-') sign = -sign;
78 p = ParseInt(p, min_hour, max_hour, &hours);
79 if (p ==
nullptr)
return nullptr;
81 p = ParseInt(p + 1, 0, 59, &minutes);
82 if (p ==
nullptr)
return nullptr;
84 p = ParseInt(p + 1, 0, 59, &seconds);
85 if (p ==
nullptr)
return nullptr;
88 *offset = sign * ((((hours * 60) + minutes) * 60) + seconds);
93 const char* ParseDateTime(
const char* p, PosixTransition* res) {
94 if (p !=
nullptr && *p ==
',') {
97 if ((p = ParseInt(p + 1, 1, 12, &month)) !=
nullptr && *p ==
'.') {
99 if ((p = ParseInt(p + 1, 1, 5, &week)) !=
nullptr && *p ==
'.') {
101 if ((p = ParseInt(p + 1, 0, 6, &weekday)) !=
nullptr) {
103 res->date.m.month =
static_cast<int_fast8_t
>(month);
104 res->date.m.week =
static_cast<int_fast8_t
>(week);
105 res->date.m.weekday =
static_cast<int_fast8_t
>(
weekday);
109 }
else if (*p ==
'J') {
111 if ((p = ParseInt(p + 1, 1, 365, &day)) !=
nullptr) {
113 res->date.j.day =
static_cast<int_fast16_t
>(day);
117 if ((p = ParseInt(p, 0, 365, &day)) !=
nullptr) {
119 res->date.j.day =
static_cast<int_fast16_t
>(day);
124 res->time.offset = 2 * 60 * 60;
125 if (*p ==
'/') p = ParseOffset(p + 1, -167, 167, 1, &res->time.offset);
134 const char* p = spec.c_str();
135 if (*p ==
':')
return false;
138 p = ParseOffset(p, 0, 24, -1, &res->
std_offset);
139 if (p ==
nullptr)
return false;
140 if (*p ==
'\0')
return true;
143 if (p ==
nullptr)
return false;
145 if (*p !=
',') p = ParseOffset(p, 0, 24, -1, &res->
dst_offset);
148 p = ParseDateTime(p, &res->
dst_end);
150 return p !=
nullptr && *p ==
'\0';
bool ParsePosixSpec(const std::string &spec, PosixTimeZone *res)
PosixTransition dst_start
std::chrono::duration< std::int_fast64_t > seconds
std::int_fast32_t std_offset
std::int_fast32_t dst_offset