28 #ifndef V8_DATEPARSER_INL_H_
29 #define V8_DATEPARSER_INL_H_
36 template <
typename Char>
41 InputReader<Char> in(unicode_cache, str);
42 DateStringTokenizer<Char> scanner(&in);
96 DateToken next_unhandled_token = ParseES5DateTime(&scanner, &day, &time, &tz);
97 if (next_unhandled_token.IsInvalid())
return false;
98 bool has_read_number = !day.IsEmpty();
100 for (DateToken token = next_unhandled_token;
101 !token.IsEndOfInput();
102 token = scanner.Next()) {
103 if (token.IsNumber()) {
104 has_read_number =
true;
105 int n = token.number();
106 if (scanner.SkipSymbol(
':')) {
107 if (scanner.SkipSymbol(
':')) {
109 if (!time.IsEmpty())
return false;
114 if (!time.Add(n))
return false;
115 if (scanner.Peek().IsSymbol(
'.')) scanner.Next();
117 }
else if (scanner.SkipSymbol(
'.') && time.IsExpecting(n)) {
119 if (!scanner.Peek().IsNumber())
return false;
120 int n = ReadMilliseconds(scanner.Next());
121 if (n < 0)
return false;
123 }
else if (tz.IsExpecting(n)) {
124 tz.SetAbsoluteMinute(n);
125 }
else if (time.IsExpecting(n)) {
129 DateToken peek = scanner.Peek();
130 if (!peek.IsEndOfInput() &&
131 !peek.IsWhiteSpace() &&
132 !peek.IsKeywordZ() &&
133 !peek.IsAsciiSign())
return false;
135 if (!day.Add(n))
return false;
136 scanner.SkipSymbol(
'-');
138 }
else if (token.IsKeyword()) {
140 KeywordType type = token.keyword_type();
141 int value = token.keyword_value();
142 if (type == AM_PM && !time.IsEmpty()) {
143 time.SetHourOffset(value);
144 }
else if (type == MONTH_NAME) {
145 day.SetNamedMonth(value);
146 scanner.SkipSymbol(
'-');
147 }
else if (type == TIME_ZONE_NAME && has_read_number) {
151 if (has_read_number)
return false;
154 if (scanner.Peek().IsNumber())
return false;
156 }
else if (token.IsAsciiSign() && (tz.IsUTC() || !time.IsEmpty())) {
158 tz.SetSign(token.ascii_sign());
161 if (scanner.Peek().IsNumber()) {
162 n = scanner.Next().number();
164 has_read_number =
true;
166 if (scanner.Peek().IsSymbol(
':')) {
167 tz.SetAbsoluteHour(n);
168 tz.SetAbsoluteMinute(kNone);
170 tz.SetAbsoluteHour(n / 100);
171 tz.SetAbsoluteMinute(n % 100);
173 }
else if ((token.IsAsciiSign() || token.IsSymbol(
')')) &&
182 return day.Write(out) && time.Write(out) && tz.Write(out);
186 template<
typename CharType>
187 DateParser::DateToken DateParser::DateStringTokenizer<CharType>::Scan() {
188 int pre_pos = in_->position();
189 if (in_->IsEnd())
return DateToken::EndOfInput();
190 if (in_->IsAsciiDigit()) {
191 int n = in_->ReadUnsignedNumeral();
192 int length = in_->position() - pre_pos;
193 return DateToken::Number(n, length);
200 if (in_->IsAsciiAlphaOrAbove()) {
201 ASSERT(KeywordTable::kPrefixLength == 3);
202 uint32_t buffer[3] = {0, 0, 0};
203 int length = in_->ReadWord(buffer, 3);
204 int index = KeywordTable::Lookup(buffer, length);
205 return DateToken::Keyword(KeywordTable::GetType(index),
206 KeywordTable::GetValue(index),
209 if (in_->SkipWhiteSpace()) {
210 return DateToken::WhiteSpace(in_->position() - pre_pos);
212 if (in_->SkipParentheses()) {
213 return DateToken::Unknown();
216 return DateToken::Unknown();
220 template <
typename Char>
221 DateParser::DateToken DateParser::ParseES5DateTime(
222 DateStringTokenizer<Char>* scanner,
225 TimeZoneComposer* tz) {
231 if (scanner->Peek().IsAsciiSign()) {
234 DateToken sign_token = scanner->Next();
235 if (!scanner->Peek().IsFixedLengthNumber(6))
return sign_token;
236 int sign = sign_token.ascii_sign();
237 int year = scanner->Next().number();
238 if (sign < 0 && year == 0)
return sign_token;
239 day->Add(sign * year);
240 }
else if (scanner->Peek().IsFixedLengthNumber(4)) {
241 day->Add(scanner->Next().number());
243 return scanner->Next();
245 if (scanner->SkipSymbol(
'-')) {
246 if (!scanner->Peek().IsFixedLengthNumber(2) ||
247 !DayComposer::IsMonth(scanner->Peek().number()))
return scanner->Next();
248 day->Add(scanner->Next().number());
249 if (scanner->SkipSymbol(
'-')) {
250 if (!scanner->Peek().IsFixedLengthNumber(2) ||
251 !DayComposer::IsDay(scanner->Peek().number()))
return scanner->Next();
252 day->Add(scanner->Next().number());
256 if (!scanner->Peek().IsKeywordType(TIME_SEPARATOR)) {
257 if (!scanner->Peek().IsEndOfInput())
return scanner->Next();
261 if (!scanner->Peek().IsFixedLengthNumber(2) ||
262 !Between(scanner->Peek().number(), 0, 24)) {
263 return DateToken::Invalid();
266 bool hour_is_24 = (scanner->Peek().number() == 24);
267 time->Add(scanner->Next().number());
268 if (!scanner->SkipSymbol(
':'))
return DateToken::Invalid();
269 if (!scanner->Peek().IsFixedLengthNumber(2) ||
270 !TimeComposer::IsMinute(scanner->Peek().number()) ||
271 (hour_is_24 && scanner->Peek().number() > 0)) {
272 return DateToken::Invalid();
274 time->Add(scanner->Next().number());
275 if (scanner->SkipSymbol(
':')) {
276 if (!scanner->Peek().IsFixedLengthNumber(2) ||
277 !TimeComposer::IsSecond(scanner->Peek().number()) ||
278 (hour_is_24 && scanner->Peek().number() > 0)) {
279 return DateToken::Invalid();
281 time->Add(scanner->Next().number());
282 if (scanner->SkipSymbol(
'.')) {
283 if (!scanner->Peek().IsNumber() ||
284 (hour_is_24 && scanner->Peek().number() > 0)) {
285 return DateToken::Invalid();
288 time->Add(ReadMilliseconds(scanner->Next()));
292 if (scanner->Peek().IsKeywordZ()) {
295 }
else if (scanner->Peek().IsSymbol(
'+') ||
296 scanner->Peek().IsSymbol(
'-')) {
297 tz->SetSign(scanner->Next().symbol() ==
'+' ? 1 : -1);
298 if (scanner->Peek().IsFixedLengthNumber(4)) {
300 int hourmin = scanner->Next().number();
301 int hour = hourmin / 100;
302 int min = hourmin % 100;
303 if (!TimeComposer::IsHour(hour) || !TimeComposer::IsMinute(min)) {
304 return DateToken::Invalid();
306 tz->SetAbsoluteHour(hour);
307 tz->SetAbsoluteMinute(min);
310 if (!scanner->Peek().IsFixedLengthNumber(2) ||
311 !TimeComposer::IsHour(scanner->Peek().number())) {
312 return DateToken::Invalid();
314 tz->SetAbsoluteHour(scanner->Next().number());
315 if (!scanner->SkipSymbol(
':'))
return DateToken::Invalid();
316 if (!scanner->Peek().IsFixedLengthNumber(2) ||
317 !TimeComposer::IsMinute(scanner->Peek().number())) {
318 return DateToken::Invalid();
320 tz->SetAbsoluteMinute(scanner->Next().number());
323 if (!scanner->Peek().IsEndOfInput())
return DateToken::Invalid();
326 if (tz->IsEmpty()) tz->Set(0);
328 return DateToken::EndOfInput();
334 #endif // V8_DATEPARSER_INL_H_
static bool Parse(Vector< Char > str, FixedArray *output, UnicodeCache *cache)
#define ASSERT(condition)
IN DWORD64 OUT PDWORD64 OUT PIMAGEHLP_SYMBOL64 Symbol