datetimeparser.cpp
来自「C++ class libraries for network-centric,」· C++ 代码 · 共 370 行
CPP
370 行
//// DateTimeParser.cpp//// $Id: //poco/1.2/Foundation/src/DateTimeParser.cpp#1 $//// Library: Foundation// Package: DateTime// Module: DateTimeParser//// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.// and Contributors.//// Permission is hereby granted, free of charge, to any person or organization// obtaining a copy of the software and accompanying documentation covered by// this license (the "Software") to use, reproduce, display, distribute,// execute, and transmit the Software, and to prepare derivative works of the// Software, and to permit third-parties to whom the Software is furnished to// do so, all subject to the following:// // The copyright notices in the Software and this entire statement, including// the above license grant, this restriction and the following disclaimer,// must be included in all copies of the Software, in whole or in part, and// all derivative works of the Software, unless such copies or derivative// works are solely in the form of machine-executable object code generated by// a source language processor.// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER// DEALINGS IN THE SOFTWARE.//#include "Poco/DateTimeParser.h"#include "Poco/DateTimeFormat.h"#include "Poco/DateTime.h"#include "Poco/Exception.h"#include <ctype.h>namespace Poco {#define SKIP_JUNK() \ while (it != end && !isdigit(*it)) ++it#define PARSE_NUMBER(var) \ while (it != end && isdigit(*it)) var = var*10 + ((*it++) - '0')#define PARSE_NUMBER_N(var, n) \ { int i = 0; while (i++ < n && it != end && isdigit(*it)) var = var*10 + ((*it++) - '0'); }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 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 && isspace(*it)) ++it; while (it != end && 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(year); if (year < 1000) { 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 'z': case 'Z': tzd = parseTZD(it, end); break; } ++itf; } } else ++itf; } if (month == 0) month = 1; if (day == 0) day = 1; dateTime.assign(year, month, day, hour, minute, second, millis); timeZoneDifferential = tzd;}DateTime DateTimeParser::parse(const std::string& fmt, const std::string& str, int& timeZoneDifferential){ DateTime result; parse(fmt, str, result, timeZoneDifferential); return result;} bool DateTimeParser::tryParse(const std::string& fmt, const std::string& str, DateTime& dateTime, int& timeZoneDifferential){ try { parse(fmt, str, dateTime, timeZoneDifferential); } catch (Exception&) { return false; } return true;}void DateTimeParser::parse(const std::string& str, DateTime& dateTime, int& timeZoneDifferential){ if (!tryParse(str, dateTime, timeZoneDifferential)) throw SyntaxException("Unsupported or invalid date/time format");} DateTime DateTimeParser::parse(const std::string& str, int& timeZoneDifferential){ DateTime result; if (tryParse(str, result, timeZoneDifferential)) return result; else throw SyntaxException("Unsupported or invalid date/time format");} bool DateTimeParser::tryParse(const std::string& str, DateTime& dateTime, int& timeZoneDifferential){ if (str.length() < 4) return false; if (str[3] == ',') return tryParse(DateTimeFormat::RFC822_FORMAT, str, dateTime, timeZoneDifferential); else if (str[3] == ' ') return tryParse(DateTimeFormat::ASCTIME_FORMAT, str, dateTime, timeZoneDifferential); else if (str.find(',') != std::string::npos) return tryParse(DateTimeFormat::RFC850_FORMAT, str, dateTime, timeZoneDifferential); else if (isdigit(str[0])) { if (str.find(' ') != std::string::npos || str.length() == 10) return tryParse(DateTimeFormat::SORTABLE_FORMAT, str, dateTime, timeZoneDifferential); else return tryParse(DateTimeFormat::ISO8601_FORMAT, str, dateTime, timeZoneDifferential); } else return false;}int DateTimeParser::parseTZD(std::string::const_iterator& it, const std::string::const_iterator& end){ struct Zone { const char* designator; int timeZoneDifferential; }; static Zone zones[] = { {"Z", 0}, {"UT", 0}, {"GMT", 0}, {"BST", 1*3600}, {"IST", 1*3600}, {"WET", 0}, {"WEST", 1*3600}, {"CET", 1*3600}, {"CEST", 2*3600}, {"EET", 2*3600}, {"EEST", 3*3600}, {"MSK", 3*3600}, {"MSD", 4*3600}, {"NST", -3*3600-1800}, {"NDT", -2*3600-1800}, {"AST", -4*3600}, {"ADT", -3*3600}, {"EST", -5*3600}, {"EDT", -4*3600}, {"CST", -6*3600}, {"CDT", -5*3600}, {"MST", -7*3600}, {"MDT", -6*3600}, {"PST", -8*3600}, {"PDT", -7*3600}, {"AKST", -9*3600}, {"AKDT", -8*3600}, {"HST", -10*3600}, {"AEST", 10*3600}, {"AEDT", 11*3600}, {"ACST", 9*3600+1800}, {"ACDT", 10*3600+1800}, {"AWST", 8*3600}, {"AWDT", 9*3600} }; while (it != end && isspace(*it)) ++it; if (it != end) { if (isalpha(*it)) { std::string designator; designator += *it++; if (it != end && isalpha(*it)) designator += *it++; if (it != end && isalpha(*it)) designator += *it++; if (it != end && isalpha(*it)) designator += *it++; for (unsigned i = 0; i < sizeof(zones)/sizeof(Zone); ++i) { if (designator == zones[i].designator) return zones[i].timeZoneDifferential; } } else if (*it == '+' || *it == '-') { int sign = *it == '+' ? 1 : -1; ++it; int hours = 0; PARSE_NUMBER_N(hours, 2); if (it != end && *it == ':') ++it; int minutes = 0; PARSE_NUMBER_N(minutes, 2); return sign*(hours*3600 + minutes*60); } } return 0;}int DateTimeParser::parseMonth(std::string::const_iterator& it, const std::string::const_iterator& end){ std::string month; while (it != end && isspace(*it) || ispunct(*it)) ++it; bool isFirst = true; while (it != end && isalpha(*it)) { char ch = (*it++); if (isFirst) { month += toupper(ch); isFirst = false; } else month += tolower(ch); } if (month.length() < 3) throw SyntaxException("Month name must be at least three characters long", month); for (int i = 0; i < 12; ++i) { if (DateTimeFormat::MONTH_NAMES[i].find(month) == 0) return i + 1; } throw SyntaxException("Not a valid month name", month);}int DateTimeParser::parseDayOfWeek(std::string::const_iterator& it, const std::string::const_iterator& end){ std::string dow; while (it != end && isspace(*it) || ispunct(*it)) ++it; bool isFirst = true; while (it != end && isalpha(*it)) { char ch = (*it++); if (isFirst) { dow += toupper(ch); isFirst = false; } else dow += tolower(ch); } if (dow.length() < 3) throw SyntaxException("Weekday name must be at least three characters long", dow); for (int i = 0; i < 7; ++i) { if (DateTimeFormat::WEEKDAY_NAMES[i].find(dow) == 0) return i; } throw SyntaxException("Not a valid weekday name", dow);}int DateTimeParser::parseAMPM(std::string::const_iterator& it, const std::string::const_iterator& end, int hour){ std::string ampm; while (it != end && isspace(*it) || ispunct(*it)) ++it; while (it != end && isalpha(*it)) { char ch = (*it++); ampm += toupper(ch); } if (ampm == "AM") { if (hour == 12) return 0; else return hour; } else if (ampm == "PM") { if (hour < 12) return hour + 12; else return hour; } else throw SyntaxException("Not a valid AM/PM designator", ampm);}} // namespace Poco
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?