diff options
Diffstat (limited to 'src/times.cc')
-rw-r--r-- | src/times.cc | 174 |
1 files changed, 84 insertions, 90 deletions
diff --git a/src/times.cc b/src/times.cc index deb51058..45f7ed10 100644 --- a/src/times.cc +++ b/src/times.cc @@ -41,64 +41,83 @@ std::string output_datetime_format = "%Y-%m-%d %H:%M:%S"; std::string output_date_format = "%Y-%m-%d"; namespace { - const char * formats[] = { - "%y/%m/%d", - "%Y/%m/%d", - "%m/%d", - "%Y/%m", - "%y.%m.%d", - "%Y.%m.%d", - "%m.%d", - "%Y.%m", - "%y-%m-%d", - "%Y-%m-%d", - "%m-%d", - "%Y-%m", - NULL + struct date_format_t { + const char * format; + bool has_year; + date_format_t(const char * _format, bool _has_year) + : format(_format), has_year(_has_year) {} }; - bool parse_date_mask(const char * date_str, std::tm& result) - { - if (input_date_format) { - std::memset(&result, -1, sizeof(std::tm)); - if (strptime(date_str, input_date_format->c_str(), &result)) - return true; - } - for (const char ** f = formats; *f; f++) { - std::memset(&result, -1, sizeof(std::tm)); - if (strptime(date_str, *f, &result)) - return true; - } - return false; - } + const date_format_t formats[] = { + date_format_t("%m/%d", false), + date_format_t("%Y/%m/%d", true), + date_format_t("%Y/%m", true), + date_format_t("%y/%m/%d", true), + date_format_t("%m.%d", false), + date_format_t("%Y.%m.%d", true), + date_format_t("%Y.%m", true), + date_format_t("%y.%m.%d", true), + date_format_t("%m-%d", false), + date_format_t("%Y-%m-%d", true), + date_format_t("%Y-%m", true), + date_format_t("%y-%m-%d", true) + }; - bool quick_parse_date(const char * date_str, std::tm& result, const int year) + date_t parse_date_mask_routine(const char * date_str, const date_format_t& df, + optional<date_t::year_type> year, bool& saw_year) { - if (! parse_date_mask(date_str, result)) - return false; + std::string str(date_str); - result.tm_hour = 0; - result.tm_min = 0; - result.tm_sec = 0; + gregorian::date_input_facet * facet(new gregorian::date_input_facet(df.format)); + std::istringstream sstr(str); + sstr.imbue(std::locale(sstr.getloc(), facet)); - if (result.tm_mday == -1) - result.tm_mday = 1; + date_t when; + sstr >> when; - if (result.tm_mon == -1) { - result.tm_mon = 0; + if (! when.is_not_a_date()) { + if (sstr.good() && ! sstr.eof() && sstr.peek() != EOF) + return date_t(); - if (result.tm_mday > (CURRENT_DATE().day() - 1)) - result.tm_mon = 11; + DEBUG("times.parse", "Parsed date string: " << date_str); + DEBUG("times.parse", "Parsed result is: " << when); + DEBUG("times.parse", "Format used was: " << df.format); + + if (! df.has_year) { + saw_year = false; + + when = date_t(year ? *year : CURRENT_DATE().year(), + when.month(), when.day()); + + if (when.month() > CURRENT_DATE().month()) + when -= gregorian::years(1); + } else { + saw_year = true; + } } + return when; + } - if (result.tm_year == -1) { - result.tm_year = (year == -1 ? int(CURRENT_DATE().year()) : year) - 1900; + date_t parse_date_mask(const char * date_str, optional<date_t::year_type> year, + bool& saw_year) + { + if (input_date_format) { + date_format_t df(input_date_format->c_str(), true); + if (! icontains(*input_date_format, "%y")) + df.has_year = false; + date_t when = parse_date_mask_routine(date_str, df, year, saw_year); + if (! when.is_not_a_date()) + return when; + } - if (year == -1 && result.tm_mon > (CURRENT_DATE().month() - 1)) - result.tm_year--; + for (uint8_t i = 0; i < (sizeof(formats) / sizeof(date_format_t)); i++) { + date_t when = parse_date_mask_routine(date_str, formats[i], year, + saw_year); + if (! when.is_not_a_date()) + return when; } - return true; + return date_t(); } } @@ -153,21 +172,24 @@ string_to_month_of_year(const std::string& str) return none; } -datetime_t parse_datetime(const char * str, int) +datetime_t parse_datetime(const char * str, optional<date_t::year_type>) { - std::tm when; - std::memset(&when, -1, sizeof(std::tm)); - if (strptime(str, "%Y/%m/%d %H:%M:%S", &when)) - return posix_time::ptime_from_tm(when); - else - return datetime_t(); + posix_time::time_input_facet * facet + (new posix_time::time_input_facet("%Y/%m/%d %H:%M:%S")); + + std::string temp(str); + std::istringstream sstr(temp); + sstr.imbue(std::locale(sstr.getloc(), facet)); + + datetime_t when; + sstr >> when; + return when; } -date_t parse_date(const char * str, int current_year) +date_t parse_date(const char * str, optional<date_t::year_type> current_year) { - std::tm when; - quick_parse_date(str, when, current_year); - return gregorian::date_from_tm(when); + bool saw_year; + return parse_date_mask(str, current_year, saw_year); } date_t date_interval_t::add_duration(const date_t& date, @@ -436,52 +458,24 @@ namespace { date_t * begin, date_t * end) { - struct std::tm when; + bool saw_year = true; + date_t when = parse_date_mask(word.c_str(), none, saw_year); - if (! parse_date_mask(word.c_str(), when)) + if (when.is_not_a_date()) throw_(date_error, _("Could not parse date mask: %1") << word); - when.tm_hour = 0; - when.tm_min = 0; - when.tm_sec = 0; - when.tm_isdst = -1; - - bool saw_year = true; - bool saw_mon = true; - bool saw_day = true; - - if (when.tm_year == -1) { - when.tm_year = CURRENT_DATE().year() - 1900; - saw_year = false; - } - if (when.tm_mon == -1) { - when.tm_mon = 0; - saw_mon = false; - } else { - saw_year = false; // don't increment by year if month used - } - if (when.tm_mday == -1) { - when.tm_mday = 1; - saw_day = false; - } else { - saw_mon = false; // don't increment by month if day used - saw_year = false; // don't increment by year if day used - } - if (begin) { - *begin = gregorian::date_from_tm(when); + *begin = when; if (end) { if (saw_year) *end = *begin + gregorian::years(1); - else if (saw_mon) + else *end = *begin + gregorian::months(1); - else if (saw_day) - *end = *begin + gregorian::days(1); } } else if (end) { - *end = gregorian::date_from_tm(when); + *end = when; } } |