diff options
author | Ian2020 <Ian2020@users.noreply.github.com> | 2023-11-29 13:12:24 +0000 |
---|---|---|
committer | John Wiegley <johnw@newartisans.com> | 2024-08-06 11:08:15 -1000 |
commit | 762353945a744ae4b89970b9e08c2c22a52ddbff (patch) | |
tree | 1e3cc5fcbe4f89c5134f0fcb7a5f7ba3a8fb372d | |
parent | b7be0a1fedfeec26e4b7d35357157d5a9209f3ee (diff) | |
download | fork-ledger-762353945a744ae4b89970b9e08c2c22a52ddbff.tar.gz fork-ledger-762353945a744ae4b89970b9e08c2c22a52ddbff.tar.bz2 fork-ledger-762353945a744ae4b89970b9e08c2c22a52ddbff.zip |
Add new --align-intervals option.
-rw-r--r-- | contrib/ledger-completion.bash | 2 | ||||
-rw-r--r-- | doc/ledger3.texi | 16 | ||||
-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 | ||||
-rw-r--r-- | test/baseline/opt-align-intervals.test | 293 |
10 files changed, 347 insertions, 19 deletions
diff --git a/contrib/ledger-completion.bash b/contrib/ledger-completion.bash index 0ef969ae..87b96f89 100644 --- a/contrib/ledger-completion.bash +++ b/contrib/ledger-completion.bash @@ -43,7 +43,7 @@ _ledger() # report.cc::lookup_option # session.cc::lookup_option # - options="--abbrev-len= --account-width= --account= --actual --actual-dates --add-budget --amount-data --amount-width= --amount= --anon --ansi --args-only --auto-match --aux-date --average --balance-format= --base --basis --begin= --bold-if= --budget --budget-format= --by-payee --cache= --change --check-payees --cleared --cleared-format= --collapse --collapse-if-zero --color --columns= --cost --count --csv-format= --current --daily --date-format= --date-width= --date= --datetime-format= --day-break --days-of-week --dc --debug= --decimal-comma --depth= --detail --deviation --display-amount= --display-total= --display= --dow --download --effective --empty --end= --equity --exact --exchange= --explicit --file= --first= --flat --force-color --force-pager --forecast-while= --forecast-years= --forecast= --format= --full-help --gain --generated --group-by= --group-title-format= --head= --help --help-calc --help-comm --help-disp --historical --immediate --init-file= --inject= --input-date-format= --invert --last= --leeway= --limit= --lot-dates --lot-notes --lot-prices --lot-tags --lots --lots-actual --market --master-account= --meta-width= --meta= --monthly --no-aliases --no-color --no-pager --no-rounding --no-titles --no-total --now= --only= --options --output= --pager= --payee-width= --payee= --pedantic --pending --percent --period-sort= --period= --permissive --pivot= --plot-amount-format= --plot-total-format= --prepend-format= --prepend-width= --price --price-db= --price-exp= --pricedb-format= --prices-format= --primary-date --quantity --quarterly --raw --real --recursive-aliases --register-format= --related --related-all --revalued --revalued-only --revalued-total= --rich-data --script= --seed= --sort-all= --sort-xacts= --sort= --start-of-week= --strict --subtotal --tail= --time-colon --time-report --total-data --total-width= --total= --trace= --truncate= --unbudgeted --uncleared --unrealized --unrealized-gains= --unrealized-losses= --unround --value --value-expr= --values --verbose --verify --verify-memory --version --weekly --wide --yearly" + options="--abbrev-len= --account-width= --account= --actual --actual-dates --add-budget --align-intervals --amount-data --amount-width= --amount= --anon --ansi --args-only --auto-match --aux-date --average --balance-format= --base --basis --begin= --bold-if= --budget --budget-format= --by-payee --cache= --change --check-payees --cleared --cleared-format= --collapse --collapse-if-zero --color --columns= --cost --count --csv-format= --current --daily --date-format= --date-width= --date= --datetime-format= --day-break --days-of-week --dc --debug= --decimal-comma --depth= --detail --deviation --display-amount= --display-total= --display= --dow --download --effective --empty --end= --equity --exact --exchange= --explicit --file= --first= --flat --force-color --force-pager --forecast-while= --forecast-years= --forecast= --format= --full-help --gain --generated --group-by= --group-title-format= --head= --help --help-calc --help-comm --help-disp --historical --immediate --init-file= --inject= --input-date-format= --invert --last= --leeway= --limit= --lot-dates --lot-notes --lot-prices --lot-tags --lots --lots-actual --market --master-account= --meta-width= --meta= --monthly --no-aliases --no-color --no-pager --no-rounding --no-titles --no-total --now= --only= --options --output= --pager= --payee-width= --payee= --pedantic --pending --percent --period-sort= --period= --permissive --pivot= --plot-amount-format= --plot-total-format= --prepend-format= --prepend-width= --price --price-db= --price-exp= --pricedb-format= --prices-format= --primary-date --quantity --quarterly --raw --real --recursive-aliases --register-format= --related --related-all --revalued --revalued-only --revalued-total= --rich-data --script= --seed= --sort-all= --sort-xacts= --sort= --start-of-week= --strict --subtotal --tail= --time-colon --time-report --total-data --total-width= --total= --trace= --truncate= --unbudgeted --uncleared --unrealized --unrealized-gains= --unrealized-losses= --unround --value --value-expr= --values --verbose --verify --verify-memory --version --weekly --wide --yearly" # Bash FAQ E13 http://tiswww.case.edu/php/chet/bash/FAQ # diff --git a/doc/ledger3.texi b/doc/ledger3.texi index f6cc6230..8c3ab3e8 100644 --- a/doc/ledger3.texi +++ b/doc/ledger3.texi @@ -6343,6 +6343,13 @@ transactions. @item --add-budget Show only unbudgeted postings. +@item --align-intervals +@findex --start-of-week @var{INT} +Use the begin time of a period expression as the start of its intervals, if +specified (@pxref{Period Expressions}). For example with a period expression of +"weekly from 2009/01/10" then the begin time of "2009/01/10 will be used as the +start of the weekly intervals. Overrides @samp{--start-of-week @var{INT}}. + @item --amount @var{EXPR} @itemx -t @var{EXPR} Apply the given value expression to the posting amount (@pxref{Value @@ -7052,9 +7059,10 @@ to sort. Sort the postings within transactions using the given value expression. @item --start-of-week @var{INT} +@findex --align-intervals Tell ledger to use a particular day of the week to start its ``weekly'' summary. @samp{--start-of-week=1} specifies Monday as the start of the -week. +week. Can be overriden by @samp{--align-intervals}. @item --subtotal @itemx -s @@ -7953,6 +7961,11 @@ October. The possible forms are: in <SPEC> @end smallexample +@findex --align-intervals +Intervals begin at the start of the week, first day of the month, +quarter or year. This can be overridden by specifying @option{--align-intervals} +which will instead use the begin time if specified. + Here are a few examples of period expressions: @smallexample @@ -7963,6 +7976,7 @@ weekly from last month from sep to oct from 10/1 to 10/5 monthly until 2005 +monthly from 2005/04/06 from apr until nov last oct 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 { diff --git a/test/baseline/opt-align-intervals.test b/test/baseline/opt-align-intervals.test new file mode 100644 index 00000000..7a11c8e6 --- /dev/null +++ b/test/baseline/opt-align-intervals.test @@ -0,0 +1,293 @@ +2008/01/01 January + Expenses:Books $10.00 + Liabilities:Cards $10.00 + Assets:Cash + +2008/01/31 End of January + Expenses:Books $10.00 + Liabilities:Cards $10.00 + Assets:Cash + +2008/02/01 February + Expenses:Books $20.00 + Liabilities:Cards $20.00 + Assets:Cash + +2008/02/28 End of February + Expenses:Books $20.00 + Liabilities:Cards $20.00 + Assets:Cash + +2008/03/01 March + Expenses:Books $30.00 + Liabilities:Cards $30.00 + Assets:Cash + +2008/03/31 End of March + Expenses:Books $30.00 + Liabilities:Cards $30.00 + Assets:Cash + +2008/04/01 April + Expenses:Books $40.00 + Liabilities:Cards $40.00 + Assets:Cash + +2008/04/30 End of April + Expenses:Books $40.00 + Liabilities:Cards $40.00 + Assets:Cash + +2008/05/01 May + Expenses:Books $50.00 + Liabilities:Cards $50.00 + Assets:Cash + +2008/05/31 End of May + Expenses:Books $50.00 + Liabilities:Cards $50.00 + Assets:Cash + +2008/06/01 June + Expenses:Books $60.00 + Liabilities:Cards $60.00 + Assets:Cash + +2008/06/30 End of June + Expenses:Books $60.00 + Liabilities:Cards $60.00 + Assets:Cash + +2008/07/01 July + Expenses:Books $70.00 + Liabilities:Cards $70.00 + Assets:Cash + +2008/07/31 End of July + Expenses:Books $70.00 + Liabilities:Cards $70.00 + Assets:Cash + +2008/08/01 August + Expenses:Books $80.00 + Liabilities:Cards $80.00 + Assets:Cash + +2008/08/31 End of August + Expenses:Books $80.00 + Liabilities:Cards $80.00 + Assets:Cash + +2008/09/01 September + Expenses:Books $90.00 + Liabilities:Cards $90.00 + Assets:Cash + +2008/09/30 End of September + Expenses:Books $90.00 + Liabilities:Cards $90.00 + Assets:Cash + +2008/10/01 October + Expenses:Books $100.00 + Liabilities:Cards $100.00 + Assets:Cash + +2008/10/31 End of October + Expenses:Books $100.00 + Liabilities:Cards $100.00 + Assets:Cash + +2008/11/01 November + Expenses:Books $110.00 + Liabilities:Cards $110.00 + Assets:Cash + +2008/11/30 End of November + Expenses:Books $110.00 + Liabilities:Cards $110.00 + Assets:Cash + +2008/12/01 December + Expenses:Books $120.00 + Liabilities:Cards $120.00 + Assets:Cash + +2008/12/31 End of December + Expenses:Books $120.00 + Liabilities:Cards $120.00 + Assets:Cash + +2009/01/01 January + Expenses:Books $10.00 + Liabilities:Cards $10.00 + Assets:Cash + +2009/01/31 End of January + Expenses:Books $10.00 + Liabilities:Cards $10.00 + Assets:Cash + +2009/02/01 February + Expenses:Books $20.00 + Liabilities:Cards $20.00 + Assets:Cash + +2009/02/28 End of February + Expenses:Books $20.00 + Liabilities:Cards $20.00 + Assets:Cash + +2009/03/01 March + Expenses:Books $30.00 + Liabilities:Cards $30.00 + Assets:Cash + +2009/03/31 End of March + Expenses:Books $30.00 + Liabilities:Cards $30.00 + Assets:Cash + +2009/04/01 April + Expenses:Books $40.00 + Liabilities:Cards $40.00 + Assets:Cash + +2009/04/30 End of April + Expenses:Books $40.00 + Liabilities:Cards $40.00 + Assets:Cash + +2009/05/01 May + Expenses:Books $50.00 + Liabilities:Cards $50.00 + Assets:Cash + +2009/05/31 End of May + Expenses:Books $50.00 + Liabilities:Cards $50.00 + Assets:Cash + +2009/06/01 June + Expenses:Books $60.00 + Liabilities:Cards $60.00 + Assets:Cash + +2009/06/30 End of June + Expenses:Books $60.00 + Liabilities:Cards $60.00 + Assets:Cash + +2009/07/01 July + Expenses:Books $70.00 + Liabilities:Cards $70.00 + Assets:Cash + +2009/07/31 End of July + Expenses:Books $70.00 + Liabilities:Cards $70.00 + Assets:Cash + +2009/08/01 August + Expenses:Books $80.00 + Liabilities:Cards $80.00 + Assets:Cash + +2009/08/31 End of August + Expenses:Books $80.00 + Liabilities:Cards $80.00 + Assets:Cash + +2009/09/01 September + Expenses:Books $90.00 + Liabilities:Cards $90.00 + Assets:Cash + +2009/09/30 End of September + Expenses:Books $90.00 + Liabilities:Cards $90.00 + Assets:Cash + +2009/10/01 October + Expenses:Books $100.00 + Liabilities:Cards $100.00 + Assets:Cash + +2009/10/31 End of October + Expenses:Books $100.00 + Liabilities:Cards $100.00 + Assets:Cash + +2009/11/01 November + Expenses:Books $110.00 + Liabilities:Cards $110.00 + Assets:Cash + +2009/11/30 End of November + Expenses:Books $110.00 + Liabilities:Cards $110.00 + Assets:Cash + +2009/12/01 December + Expenses:Books $120.00 + Liabilities:Cards $120.00 + Assets:Cash + +2009/12/31 End of December + Expenses:Books $120.00 + Liabilities:Cards $120.00 + Assets:Cash + +test reg -p "weekly from 2009/11/26" --align-intervals +09-Nov-26 - 09-Dec-02 Assets:Cash $-460.00 $-460.00 + Expenses:Books $230.00 $-230.00 + Liabilities:Cards $230.00 0 +09-Dec-31 - 10-Jan-06 Assets:Cash $-240.00 $-240.00 + Expenses:Books $120.00 $-120.00 + Liabilities:Cards $120.00 0 +end test + +test reg -p "monthly from 2009/11/15" --align-intervals +09-Nov-15 - 09-Dec-14 Assets:Cash $-460.00 $-460.00 + Expenses:Books $230.00 $-230.00 + Liabilities:Cards $230.00 0 +09-Dec-15 - 10-Jan-14 Assets:Cash $-240.00 $-240.00 + Expenses:Books $120.00 $-120.00 + Liabilities:Cards $120.00 0 +end test + +test reg -p "quarterly from 2008/01/15" --align-intervals +08-Jan-15 - 08-Apr-14 Assets:Cash $-300.00 $-300.00 + Expenses:Books $150.00 $-150.00 + Liabilities:Cards $150.00 0 +08-Apr-15 - 08-Jul-14 Assets:Cash $-660.00 $-660.00 + Expenses:Books $330.00 $-330.00 + Liabilities:Cards $330.00 0 +08-Jul-15 - 08-Oct-14 Assets:Cash $-1020.00 $-1020.00 + Expenses:Books $510.00 $-510.00 + Liabilities:Cards $510.00 0 +08-Oct-15 - 09-Jan-14 Assets:Cash $-1140.00 $-1140.00 + Expenses:Books $570.00 $-570.00 + Liabilities:Cards $570.00 0 +09-Jan-15 - 09-Apr-14 Assets:Cash $-300.00 $-300.00 + Expenses:Books $150.00 $-150.00 + Liabilities:Cards $150.00 0 +09-Apr-15 - 09-Jul-14 Assets:Cash $-660.00 $-660.00 + Expenses:Books $330.00 $-330.00 + Liabilities:Cards $330.00 0 +09-Jul-15 - 09-Oct-14 Assets:Cash $-1020.00 $-1020.00 + Expenses:Books $510.00 $-510.00 + Liabilities:Cards $510.00 0 +09-Oct-15 - 10-Jan-14 Assets:Cash $-1120.00 $-1120.00 + Expenses:Books $560.00 $-560.00 + Liabilities:Cards $560.00 0 +end test + +test reg -p "yearly from 2008/02/28" --align-intervals +08-Feb-28 - 09-Feb-27 Assets:Cash $-3120.00 $-3120.00 + Expenses:Books $1560.00 $-1560.00 + Liabilities:Cards $1560.00 0 +09-Feb-28 - 10-Feb-27 Assets:Cash $-3040.00 $-3040.00 + Expenses:Books $1520.00 $-1520.00 + Liabilities:Cards $1520.00 0 +end test |