diff options
author | John Wiegley <johnw@newartisans.com> | 2009-02-21 02:08:49 -0400 |
---|---|---|
committer | John Wiegley <johnw@newartisans.com> | 2009-02-21 02:10:02 -0400 |
commit | a93111470d54e6345617b51fcc939f306854a524 (patch) | |
tree | 8a514e7f3d696ba6134907f7296c370c55a1811e | |
parent | 4ff8087815c9d93447ddb1651fa3ec8b82bba9be (diff) | |
download | fork-ledger-a93111470d54e6345617b51fcc939f306854a524.tar.gz fork-ledger-a93111470d54e6345617b51fcc939f306854a524.tar.bz2 fork-ledger-a93111470d54e6345617b51fcc939f306854a524.zip |
Greatly improved the way "weeks" are iterated
-rw-r--r-- | src/derive.cc | 20 | ||||
-rw-r--r-- | src/textual.cc | 2 | ||||
-rw-r--r-- | src/times.cc | 52 | ||||
-rw-r--r-- | src/times.h | 21 |
4 files changed, 61 insertions, 34 deletions
diff --git a/src/derive.cc b/src/derive.cc index ea9e7483..a71dc8bb 100644 --- a/src/derive.cc +++ b/src/derive.cc @@ -124,26 +124,6 @@ namespace { } }; - short string_to_day_of_week(const std::string& str) - { - if (str == "sun") - return 0; - else if (str == "mon") - return 1; - else if (str == "tue") - return 2; - else if (str == "wed") - return 3; - else if (str == "thu") - return 4; - else if (str == "fri") - return 5; - else if (str == "sat") - return 6; - assert(false); - return -1; - } - entry_template_t args_to_entry_template(value_t::sequence_t::const_iterator begin, value_t::sequence_t::const_iterator end) diff --git a/src/textual.cc b/src/textual.cc index eec3be61..b3fb2f2e 100644 --- a/src/textual.cc +++ b/src/textual.cc @@ -512,7 +512,7 @@ void instance_t::nomarket_directive(char * line) void instance_t::year_directive(char * line) { - current_year = std::atoi(skip_ws(line + 1)); + current_year = lexical_cast<int>(skip_ws(line + 1)); } void instance_t::option_directive(char * line) diff --git a/src/times.cc b/src/times.cc index df760d10..b10d9884 100644 --- a/src/times.cc +++ b/src/times.cc @@ -33,6 +33,7 @@ namespace ledger { +int start_of_week = 0; optional<std::string> input_date_format; std::string output_datetime_format = "%Y-%m-%d %H:%M:%S"; std::string output_date_format = "%Y-%m-%d"; @@ -58,9 +59,7 @@ namespace { "%Y", NULL }; -} -namespace { bool parse_date_mask(const char * date_str, std::tm& result) { if (input_date_format) { @@ -106,6 +105,27 @@ namespace { } } +int string_to_day_of_week(const std::string& str) +{ + if (str == "sun" || str == "sunday" || str == "0") + return 0; + else if (str == "mon" || str == "monday" || str == "1") + return 1; + else if (str == "tue" || str == "tuesday" || str == "2") + return 2; + else if (str == "wed" || str == "wednesday" || str == "3") + return 3; + else if (str == "thu" || str == "thursday" || str == "4") + return 4; + else if (str == "fri" || str == "friday" || str == "5") + return 5; + else if (str == "sat" || str == "saturday" || str == "6") + return 6; + + assert(false); + return -1; +} + datetime_t parse_datetime(const char * str, int) { std::tm when; @@ -130,7 +150,19 @@ date_t interval_t::first(const optional<date_t>& moment) // 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. - begin = date_t(moment->year(), gregorian::Jan, 1); + assert(moment); + + if (months > 0 || years > 0) { + begin = date_t(moment->year(), gregorian::Jan, 1); + } else { + begin = date_t(*moment - gregorian::days(400)); + + // jww (2009-02-21): Add support for starting a week on any day + if (weekly) { // move it to a Sunday + while (begin.day_of_week() != start_of_week) + begin += gregorian::days(1); + } + } } date_t quant(begin); @@ -281,12 +313,14 @@ void interval_t::parse(std::istream& in) if (word == "every") { read_lower_word(in, word); if (std::isdigit(word[0])) { - int quantity = std::atol(word.c_str()); + int quantity = lexical_cast<int>(word); read_lower_word(in, word); if (word == "days") days = quantity; - else if (word == "weeks") + else if (word == "weeks") { days = 7 * quantity; + weekly = true; + } else if (word == "months") months = quantity; else if (word == "quarters") @@ -296,8 +330,10 @@ void interval_t::parse(std::istream& in) } else if (word == "day") days = 1; - else if (word == "week") + else if (word == "week") { days = 7; + weekly = true; + } else if (word == "month") months = 1; else if (word == "quarter") @@ -307,8 +343,10 @@ void interval_t::parse(std::istream& in) } else if (word == "daily") days = 1; - else if (word == "weekly") + else if (word == "weekly") { days = 7; + weekly = true; + } else if (word == "biweekly") days = 14; else if (word == "monthly") diff --git a/src/times.h b/src/times.h index 54c1dc80..8e0f72f9 100644 --- a/src/times.h +++ b/src/times.h @@ -70,8 +70,11 @@ inline bool is_valid(const date_t& moment) { #endif #define CURRENT_DATE() boost::gregorian::day_clock::universal_day() +extern int start_of_week; extern optional<std::string> input_date_format; +int string_to_day_of_week(const std::string& str); + datetime_t parse_datetime(const char * str, int current_year = -1); inline datetime_t parse_datetime(const std::string& str, int current_year = -1) { @@ -128,26 +131,32 @@ struct interval_t int years; int months; int days; + bool weekly; date_t begin; date_t end; - interval_t(int _days = 0, int _months = 0, int _years = 0, - const date_t& _begin = date_t(), - const date_t& _end = date_t()) + interval_t(int _days = 0, + int _months = 0, + int _years = 0, + bool _weekly = false, + const date_t& _begin = date_t(), + const date_t& _end = date_t()) : years(_years), months(_months), days(_days), - begin(_begin), end(_end) { - TRACE_CTOR(interval_t, "int, int, int, const date_t&, const date_t&"); + weekly(_weekly), begin(_begin), end(_end) { + TRACE_CTOR(interval_t, + "int, int, int, bool, const date_t&, const date_t&"); } interval_t(const interval_t& other) : years(other.years), months(other.months), days(other.days), + weekly(other.weekly), begin(other.begin), end(other.end) { TRACE_CTOR(interval_t, "copy"); } interval_t(const string& desc) - : years(0), months(0), days(0), begin(), end() { + : years(0), months(0), days(0), weekly(false), begin(), end() { TRACE_CTOR(interval_t, "const string&"); std::istringstream stream(desc); parse(stream); |