diff options
Diffstat (limited to 'src/times.cc')
-rw-r--r-- | src/times.cc | 159 |
1 files changed, 99 insertions, 60 deletions
diff --git a/src/times.cc b/src/times.cc index a9768f4f..31367e34 100644 --- a/src/times.cc +++ b/src/times.cc @@ -194,7 +194,6 @@ namespace { std::deque<shared_ptr<date_io_t> > readers; date_t parse_date_mask_routine(const char * date_str, date_io_t& io, - optional_year year, date_traits_t * traits = NULL) { VERIFY(std::strlen(date_str) < 127); @@ -229,29 +228,26 @@ namespace { *traits = io.traits; if (! io.traits.has_year) { - when = date_t(year ? *year : CURRENT_DATE().year(), - when.month(), when.day()); + when = date_t(CURRENT_DATE().year(), when.month(), when.day()); - if (! year && when.month() > CURRENT_DATE().month()) + if (when.month() > CURRENT_DATE().month()) when -= gregorian::years(1); } } return when; } - date_t parse_date_mask(const char * date_str, optional_year year, - date_traits_t * traits = NULL) + date_t parse_date_mask(const char * date_str, date_traits_t * traits = NULL) { if (input_date_io.get()) { date_t when = parse_date_mask_routine(date_str, *input_date_io.get(), - year, traits); + traits); if (! when.is_not_a_date()) return when; } foreach (shared_ptr<date_io_t>& reader, readers) { - date_t when = parse_date_mask_routine(date_str, *reader.get(), - year, traits); + date_t when = parse_date_mask_routine(date_str, *reader.get(), traits); if (! when.is_not_a_date()) return when; } @@ -312,7 +308,7 @@ string_to_month_of_year(const std::string& str) return none; } -datetime_t parse_datetime(const char * str, optional_year) +datetime_t parse_datetime(const char * str) { datetime_t when = input_datetime_io->parse(str); if (when.is_not_a_date_time()) @@ -320,18 +316,16 @@ datetime_t parse_datetime(const char * str, optional_year) return when; } -date_t parse_date(const char * str, optional_year current_year) +date_t parse_date(const char * str) { - return parse_date_mask(str, current_year); + return parse_date_mask(str); } -date_t date_specifier_t::begin(const optional_year& current_year) const +date_t date_specifier_t::begin() const { - assert(year || current_year); - - year_type the_year = year ? *year : static_cast<year_type>(*current_year); + year_type the_year = year ? *year : year_type(CURRENT_DATE().year()); month_type the_month = month ? *month : date_t::month_type(1); - day_type the_day = day ? *day : date_t::day_type(1); + day_type the_day = day ? *day : date_t::day_type(1); #if !defined(NO_ASSERTS) if (day) @@ -348,14 +342,14 @@ date_t date_specifier_t::begin(const optional_year& current_year) const static_cast<date_t::day_type>(the_day)); } -date_t date_specifier_t::end(const optional_year& current_year) const +date_t date_specifier_t::end() const { if (day || wday) - return begin(current_year) + gregorian::days(1); + return begin() + gregorian::days(1); else if (month) - return begin(current_year) + gregorian::months(1); + return begin() + gregorian::months(1); else if (year) - return begin(current_year) + gregorian::years(1); + return begin() + gregorian::years(1); else { assert(false); return date_t(); @@ -667,6 +661,16 @@ void date_parser_t::determine_when(date_parser_t::lexer_t::token_t& tok, (boost::get<date_time::weekdays>(*tok.value)); break; + case lexer_t::token_t::TOK_TODAY: + specifier = date_specifier_t(CURRENT_DATE()); + break; + case lexer_t::token_t::TOK_TOMORROW: + specifier = date_specifier_t(CURRENT_DATE() + gregorian::days(1)); + break; + case lexer_t::token_t::TOK_YESTERDAY: + specifier = date_specifier_t(CURRENT_DATE() - gregorian::days(1)); + break; + default: tok.unexpected(); break; @@ -687,14 +691,6 @@ date_interval_t date_parser_t::parse() tok.kind != lexer_t::token_t::END_REACHED; tok = lexer.next_token()) { switch (tok.kind) { -#if 0 - case lexer_t::token_t::TOK_INT: - // jww (2009-11-18): NYI - assert(! "Need to allow for expressions like \"4 months ago\""); - tok.unexpected(); - break; -#endif - case lexer_t::token_t::TOK_DATE: if (! inclusion_specifier) inclusion_specifier = date_specifier_t(); @@ -782,11 +778,44 @@ date_interval_t date_parser_t::parse() tok = lexer.next_token(); switch (tok.kind) { - case lexer_t::token_t::TOK_INT: - // jww (2009-11-18): Allow things like "last 5 weeks" - assert(! "Need to allow for expressions like \"last 5 weeks\""); - tok.unexpected(); + case lexer_t::token_t::TOK_INT: { + unsigned short amount = boost::get<unsigned short>(*tok.value); + + date_t base(today); + date_t end(today); + + tok = lexer.next_token(); + switch (tok.kind) { + case lexer_t::token_t::TOK_YEARS: + base += gregorian::years(amount * adjust); + break; + case lexer_t::token_t::TOK_QUARTERS: + base += gregorian::months(amount * adjust * 3); + break; + case lexer_t::token_t::TOK_MONTHS: + base += gregorian::months(amount * adjust); + break; + case lexer_t::token_t::TOK_WEEKS: + base += gregorian::weeks(amount * adjust); + break; + case lexer_t::token_t::TOK_DAYS: + base += gregorian::days(amount * adjust); + break; + default: + tok.unexpected(); + break; + } + + if (adjust >= 0) { + date_t temp = base; + base = end; + end = temp; + } + + since_specifier = date_specifier_t(base); + until_specifier = date_specifier_t(end); break; + } case lexer_t::token_t::TOK_A_MONTH: { inclusion_specifier = date_specifier_t(); @@ -822,26 +851,40 @@ date_interval_t date_parser_t::parse() } case lexer_t::token_t::TOK_QUARTER: { - date_t temp = + date_t base = date_duration_t::find_nearest(today, date_duration_t::QUARTERS); - temp += gregorian::months(3 * adjust); - inclusion_specifier = - date_specifier_t(static_cast<date_specifier_t::year_type>(temp.year()), - temp.month()); -#if 0 - period.duration = date_duration_t(date_duration_t::QUARTERS, 1); -#endif + date_t temp; + if (adjust < 0) { + temp = base + gregorian::months(3 * adjust); + } + else if (adjust == 0) { + temp = base + gregorian::months(3); + } + else if (adjust > 0) { + base += gregorian::months(3 * adjust); + temp = base + gregorian::months(3 * adjust); + } + since_specifier = date_specifier_t(adjust < 0 ? temp : base); + until_specifier = date_specifier_t(adjust < 0 ? base : temp); break; } case lexer_t::token_t::TOK_WEEK: { - date_t temp = + date_t base = date_duration_t::find_nearest(today, date_duration_t::WEEKS); - temp += gregorian::days(7 * adjust); - inclusion_specifier = date_specifier_t(today); -#if 0 - period.duration = date_duration_t(date_duration_t::WEEKS, 1); -#endif + date_t temp; + if (adjust < 0) { + temp = base + gregorian::days(7 * adjust); + } + else if (adjust == 0) { + temp = base + gregorian::days(7); + } + else if (adjust > 0) { + base += gregorian::days(7 * adjust); + temp = base + gregorian::days(7 * adjust); + } + since_specifier = date_specifier_t(adjust < 0 ? temp : base); + until_specifier = date_specifier_t(adjust < 0 ? base : temp); break; } @@ -862,6 +905,7 @@ date_interval_t date_parser_t::parse() break; } } + break; } case lexer_t::token_t::TOK_TODAY: @@ -876,7 +920,7 @@ date_interval_t date_parser_t::parse() case lexer_t::token_t::TOK_EVERY: tok = lexer.next_token(); - if (tok == lexer_t::token_t::TOK_INT) { + if (tok.kind == lexer_t::token_t::TOK_INT) { int quantity = boost::get<unsigned short>(*tok.value); tok = lexer.next_token(); switch (tok.kind) { @@ -1052,8 +1096,8 @@ void date_interval_t::stabilize(const optional<date_t>& date) // want a date early enough that the range will be correct, but late // enough that we don't spend hundreds of thousands of loops skipping // through time. - optional<date_t> initial_start = start ? start : begin(date->year()); - optional<date_t> initial_finish = finish ? finish : end(date->year()); + optional<date_t> initial_start = start ? start : begin(); + optional<date_t> initial_finish = finish ? finish : end(); #if defined(DEBUG_ON) if (initial_start) @@ -1116,13 +1160,8 @@ void date_interval_t::stabilize(const optional<date_t>& date) #endif } else if (range) { - if (date) { - start = range->begin(date->year()); - finish = range->end(date->year()); - } else { - start = range->begin(); - finish = range->end(); - } + start = range->begin(); + finish = range->end(); } aligned = true; } @@ -1228,7 +1267,7 @@ date_interval_t& date_interval_t::operator++() return *this; } -void date_interval_t::dump(std::ostream& out, optional_year current_year) +void date_interval_t::dump(std::ostream& out) { out << _("--- Before stabilization ---") << std::endl; @@ -1242,7 +1281,7 @@ void date_interval_t::dump(std::ostream& out, optional_year current_year) if (duration) out << _("duration: ") << duration->to_string() << std::endl; - stabilize(begin(current_year)); + stabilize(begin()); out << std::endl << _("--- After stabilization ---") << std::endl; @@ -1317,7 +1356,7 @@ date_parser_t::lexer_t::token_t date_parser_t::lexer_t::next_token() try { date_traits_t traits; - date_t when = parse_date_mask(possible_date.c_str(), none, &traits); + date_t when = parse_date_mask(possible_date.c_str(), &traits); if (! when.is_not_a_date()) { begin = i; return token_t(token_t::TOK_DATE, |