diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/chain.cc | 3 | ||||
-rw-r--r-- | src/filters.cc | 6 | ||||
-rw-r--r-- | src/filters.h | 7 | ||||
-rw-r--r-- | src/report.cc | 1 | ||||
-rw-r--r-- | src/report.h | 3 | ||||
-rw-r--r-- | src/times.cc | 22 | ||||
-rw-r--r-- | src/times.h | 13 |
7 files changed, 38 insertions, 17 deletions
diff --git a/src/chain.cc b/src/chain.cc index 8c4f8599..a103f7f8 100644 --- a/src/chain.cc +++ b/src/chain.cc @@ -229,7 +229,8 @@ post_handler_ptr chain_post_handlers(post_handler_ptr base_handler, handler.reset(new interval_posts(handler, expr, report.HANDLER(period_).str(), report.HANDLED(exact), - report.HANDLED(empty))); + report.HANDLED(empty), + report.HANDLED(align_intervals))); if (report.HANDLED(date_)) handler.reset(new transfer_details(handler, transfer_details::SET_DATE, diff --git a/src/filters.cc b/src/filters.cc index 3acb5624..b5b7fb19 100644 --- a/src/filters.cc +++ b/src/filters.cc @@ -974,7 +974,7 @@ void interval_posts::operator()(post_t& post) if (interval.duration) { all_posts.push_back(&post); } - else if (interval.find_period(post.date())) { + else if (interval.find_period(post.date(), align_intervals)) { item_handler<post_t>::operator()(post); } } @@ -991,10 +991,10 @@ void interval_posts::flush() sort_posts_by_date()); // only if the interval has no start use the earliest post - if (!(interval.begin() && interval.find_period(*interval.begin()))) + if (!(interval.begin() && interval.find_period(*interval.begin(), align_intervals))) // Determine the beginning interval by using the earliest post if (all_posts.size() > 0 && all_posts.front() - && !interval.find_period(all_posts.front()->date())) + && !interval.find_period(all_posts.front()->date(), align_intervals)) throw_(std::logic_error, _("Failed to find period for interval report")); // Walk the interval forward reporting all posts within each one diff --git a/src/filters.h b/src/filters.h index 18bf912d..a4cec5b6 100644 --- a/src/filters.h +++ b/src/filters.h @@ -731,6 +731,7 @@ class interval_posts : public subtotal_posts account_t * empty_account; bool exact_periods; bool generate_empty_posts; + bool align_intervals; std::deque<post_t *> all_posts; @@ -742,10 +743,12 @@ public: expr_t& amount_expr, const date_interval_t& _interval, bool _exact_periods = false, - bool _generate_empty_posts = false) + bool _generate_empty_posts = false, + bool _align_intervals = false) : subtotal_posts(_handler, amount_expr), start_interval(_interval), interval(start_interval), exact_periods(_exact_periods), - generate_empty_posts(_generate_empty_posts) { + generate_empty_posts(_generate_empty_posts), + align_intervals(_align_intervals) { create_accounts(); TRACE_CTOR(interval_posts, "post_handler_ptr, expr_t&, date_interval_t, bool, bool"); diff --git a/src/report.cc b/src/report.cc index 6c957767..d632a0d2 100644 --- a/src/report.cc +++ b/src/report.cc @@ -1150,6 +1150,7 @@ option_t<report_t> * report_t::lookup_option(const char * p) else OPT(amount_); else OPT(amount_data); else OPT_ALT(primary_date, actual_dates); + else OPT(align_intervals); else OPT(anon); else OPT_ALT(color, ansi); else OPT(auto_match); diff --git a/src/report.h b/src/report.h index daa9c7c0..318a4ad6 100644 --- a/src/report.h +++ b/src/report.h @@ -246,6 +246,7 @@ public: HANDLER(account_).report(out); HANDLER(actual).report(out); HANDLER(add_budget).report(out); + HANDLER(align_intervals).report(out); HANDLER(amount_).report(out); HANDLER(amount_data).report(out); HANDLER(anon).report(out); @@ -396,6 +397,8 @@ public: parent->budget_flags |= BUDGET_BUDGETED | BUDGET_UNBUDGETED; }); + OPTION(report_t, align_intervals); + OPTION__ (report_t, amount_, // -t DECL1(report_t, amount_, merged_expr_t, expr, ("amount_expr", "amount")) {} diff --git a/src/times.cc b/src/times.cc index 2c45cfcf..b66a6e30 100644 --- a/src/times.cc +++ b/src/times.cc @@ -1112,6 +1112,7 @@ date_interval_t date_parser_t::parse() range.end_inclusive = end_inclusive; period.range = date_specifier_or_range_t(range); + period.since_specified = static_cast<bool>(since_specifier); } else if (inclusion_specifier) { period.range = date_specifier_or_range_t(*inclusion_specifier); @@ -1180,7 +1181,7 @@ date_t date_duration_t::find_nearest(const date_t& date, skip_quantum_t skip) return result; } -void date_interval_t::stabilize(const optional<date_t>& date) +void date_interval_t::stabilize(const optional<date_t>& date, bool align_intervals) { #if DEBUG_ON if (date) @@ -1220,7 +1221,11 @@ void date_interval_t::stabilize(const optional<date_t>& date) // These start on most recent period start quantum before when DEBUG("times.interval", "stabilize: monthly, quarterly or yearly duration"); - start = date_duration_t::find_nearest(when, duration->quantum); + if (align_intervals && since_specified) { + start = when; + } else { + start = date_duration_t::find_nearest(when, duration->quantum); + } break; case date_duration_t::WEEKS: // Weeks start on the beginning of week prior to 400 remainder period length @@ -1228,9 +1233,13 @@ void date_interval_t::stabilize(const optional<date_t>& date) // implies period is never less than 400 days not too unreasonable DEBUG("times.interval", "stabilize: weekly duration"); { - int period = duration->length * 7; - start = date_duration_t::find_nearest( - when - gregorian::days(period + 400 % period), duration->quantum); + if (align_intervals && since_specified) { + start = when; + } else { + int period = duration->length * 7; + start = date_duration_t::find_nearest( + when - gregorian::days(period + 400 % period), duration->quantum); + } } break; default: @@ -1298,9 +1307,10 @@ void date_interval_t::stabilize(const optional<date_t>& date) } bool date_interval_t::find_period(const date_t& date, + const bool align_intervals, const bool allow_shift) { - stabilize(date); + stabilize(date, align_intervals); if (finish && date > *finish) { DEBUG("times.interval", diff --git a/src/times.h b/src/times.h index b9d48521..b0aa6e9f 100644 --- a/src/times.h +++ b/src/times.h @@ -451,6 +451,7 @@ public: optional<date_t> next; optional<date_duration_t> duration; optional<date_t> end_of_duration; + bool since_specified = false; explicit date_interval_t() : aligned(false) { TRACE_CTOR(date_interval_t, ""); @@ -466,7 +467,8 @@ public: aligned(other.aligned), next(other.next), duration(other.duration), - end_of_duration(other.end_of_duration) { + end_of_duration(other.end_of_duration), + since_specified(other.since_specified) { TRACE_CTOR(date_interval_t, "copy"); } ~date_interval_t() throw() { @@ -496,7 +498,7 @@ public: void parse(const string& str); void resolve_end(); - void stabilize(const optional<date_t>& date = none); + void stabilize(const optional<date_t>& date = none, bool align_intervals = false); bool is_valid() const { return static_cast<bool>(start); @@ -505,10 +507,11 @@ public: /** Find the current or next period containing date. Returns false if no such period can be found. If allow_shift is true, the default, then the interval may be shifted in time to find the period. */ - bool find_period(const date_t& date = CURRENT_DATE(), - const bool allow_shift = true); + bool find_period(const date_t& date = CURRENT_DATE(), + const bool align_intervals = false, + const bool allow_shift = true); bool within_period(const date_t& date = CURRENT_DATE()) { - return find_period(date, false); + return find_period(date, false, false); } optional<date_t> inclusive_end() const { |