static void testMonthParsing() { const char *months[] = { "Jan/", "Feb/", "Mar/", "Apr/", "May/", "Jun/", "Jul/", "Aug/", "Sep/", "Oct/", "Nov/", "Dec/" }; for(int i=0; i<12; i++) { for(int j=0; j<10; j++) { int rv=parseMonth(months[i]); if(i != rv) { std::cerr << "Expected " << i << " for " << months[i] << " got " << rv << std::endl; abort(); } } } for(int j=0; j<10; j++) { for(int i=0; i<12; i++) { int rv=parseMonth(months[i]); if(i != rv) { std::cerr << "Expected " << i << " for " << months[i] << " got " << rv << std::endl; abort(); } } } }
const char* parseTime(const char* start, const char* const end, unsigned& t) { t = 0; tm tm; auto comma = std::find(start, end, ','); if (comma != end) { start = comma + 1; auto hyphen = std::find(start, end, '-'); if (hyphen != end) { // RFC 850: Weekday, 00-Mon-00 00:00:00 GMT start = parseDigits(start, end, tm.tm_mday); start = parseMonth(++start, end, tm.tm_mon); start = parseDigits(++start, end, tm.tm_year); start = parseDigits(start, end, tm.tm_hour); start = parseDigits(++start, end, tm.tm_min); start = parseDigits(++start, end, tm.tm_sec); if (tm.tm_year < 70) tm.tm_year += 100; } else { // RFC 1123: Wkd, 00 Mon 0000 00:00:00 GMT start = parseDigits(start, end, tm.tm_mday); start = parseMonth(start, end, tm.tm_mon); start = parseDigits(start, end, tm.tm_year); tm.tm_year -= 1900; start = parseDigits(start, end, tm.tm_hour); start = parseDigits(++start, end, tm.tm_min); start = parseDigits(++start, end, tm.tm_sec); } } else { // asctime: Wkd Mon 00 00:00:00 0000 GMT start = skipSpace(start, end); start = std::find(start, end, ' '); if (start == end) return end; start = parseMonth(start, end, tm.tm_mon); start = parseDigits(start, end, tm.tm_mday); start = parseDigits(start, end, tm.tm_hour); start = parseDigits(++start, end, tm.tm_min); start = parseDigits(++start, end, tm.tm_sec); start = parseDigits(start, end, tm.tm_year); tm.tm_year -= 1900; } if (tm.tm_sec < 0 || 59 < tm.tm_sec || tm.tm_min < 0 || 59 < tm.tm_min || tm.tm_hour < 0 || 23 < tm.tm_hour || tm.tm_mday < 1 || 31 < tm.tm_mday || tm.tm_mon < 0 || 11 < tm.tm_mon || tm.tm_year < 70 || 120 < tm.tm_year) { return start; } t = timegm(&tm); return start; }
CommandBase* ParserList::makeCmdListSpecificMonth(string monthStr) { int parsedMonth; // Parse month, if month is valid try { parsedMonth = parseMonth(monthStr); } catch (invalid_argument) { return NULL; } // Ensure that the month is the coming month, and not a month which // has already passed date currentDate = second_clock::local_time().date(); date startDate = date(currentDate.year(), parsedMonth, 1); if (currentDate.month() > parsedMonth) { startDate += years(1); } ptime startTime = ptime(startDate); ptime endTime = getLastOfMonth(startTime); return makeCmdListPeriod(startTime, endTime); }
bool DateComponents::parseDate(const String& src, unsigned start, unsigned& end) { unsigned index; if (!parseMonth(src, start, index)) return false; // '-' and 2-digits are needed. if (index + 2 >= src.length()) return false; if (src[index] != '-') return false; ++index; int day; if (!toInt(src, index, 2, day) || day < 1 || day > maxDayOfMonth(m_year, m_month)) return false; if (!withinHTMLDateLimits(m_year, m_month, day)) return false; m_monthDay = day; end = index + 2; m_type = Date; return true; }
void DateTimeParser::parse(const std::string& fmt, const std::string& str, DateTime& dateTime, int& timeZoneDifferential) { int year = 0; int month = 0; int day = 0; int hour = 0; int minute = 0; int second = 0; int millis = 0; int micros = 0; int tzd = 0; std::string::const_iterator it = str.begin(); std::string::const_iterator end = str.end(); std::string::const_iterator itf = fmt.begin(); std::string::const_iterator endf = fmt.end(); while (itf != endf && it != end) { if (*itf == '%') { if (++itf != endf) { switch (*itf) { case 'w': case 'W': while (it != end && std::isspace(*it)) ++it; while (it != end && std::isalpha(*it)) ++it; break; case 'b': case 'B': month = parseMonth(it, end); break; case 'd': case 'e': case 'f': SKIP_JUNK(); PARSE_NUMBER_N(day, 2); break; case 'm': case 'n': case 'o': SKIP_JUNK(); PARSE_NUMBER_N(month, 2); break; case 'y': SKIP_JUNK(); PARSE_NUMBER_N(year, 2); if (year >= 70) year += 1900; else year += 2000; break; case 'Y': SKIP_JUNK(); PARSE_NUMBER_N(year, 4); break; case 'H': case 'h': SKIP_JUNK(); PARSE_NUMBER_N(hour, 2); break; case 'a': case 'A': hour = parseAMPM(it, end, hour); break; case 'M': SKIP_JUNK(); PARSE_NUMBER_N(minute, 2); break; case 'S': SKIP_JUNK(); PARSE_NUMBER_N(second, 2); break; case 'i': SKIP_JUNK(); PARSE_NUMBER_N(millis, 3); break; case 'c': SKIP_JUNK(); PARSE_NUMBER_N(millis, 1); millis *= 100; break; case 'F': SKIP_JUNK(); PARSE_NUMBER_N(millis, 3); PARSE_NUMBER_N(micros, 3); break; case 'z': case 'Z': tzd = parseTZD(it, end); break; } ++itf; } } else ++itf; } if (month == 0) month = 1; if (day == 0) day = 1; if (DateTime::isValid(year, month, day, hour, minute, second, millis, micros)) dateTime.assign(year, month, day, hour, minute, second, millis, micros); else throw SyntaxException("date/time component out of range"); timeZoneDifferential = tzd; }
time_t LogFile::parseTimestamp() { const char *p; assert(!line.empty()); timestamp=-1; p=line.c_str(); try { /* The shortest line I can parse is about 32 characters. */ if(line.length() < 32) { /* This is a broken entry */ fprintf(stderr, "Broken log entry (too short): %s\n", p); } else if(index(p, '[') != NULL) { struct tm tm; memset(&tm, 0x00, sizeof(tm)); p=index(p, '['); /* Input validation */ if(p == NULL || line.length() < 32) { std::cerr << "Invalid log line: " << line << std::endl; throw BadTimestamp(); } /* fprintf(stderr, "**** Parsing %s\n", p); */ p++; tm.tm_mday=atoi(p); p+=3; tm.tm_mon=parseMonth(p); p+=4; tm.tm_year=atoi(p); p+=5; tm.tm_hour=atoi(p); p+=3; tm.tm_min=atoi(p); p+=3; tm.tm_sec=atoi(p); /* Make sure it still looks like CLF */ if(p[2] != ' ') { std::cerr << "log line is starting to not look like CLF: " << line << std::endl; throw BadTimestamp(); } tm.tm_year-=1900; /* Let mktime guess the timezone */ tm.tm_isdst=-1; timestamp=mktime(&tm); } else { fprintf(stderr, "Unknown log format: %s\n", p); } } catch(BadTimestamp e) { // Damn. } if(timestamp < 0) { std::cerr << "* Error parsing timestamp from " << line << std::endl; } return(timestamp); }