hledger
hledger copied to clipboard
"every Nth day" periodic rule violating start date
Reported on the mail list by LucaBH. Here's a small repro:
~ every 31st day from 2024-07 to 2024-09
(a) 1
$ hledger -f a.j print --forecast=2024
2024-06-30 ; <- we don't expect this one to be generated
(a) 1
2024-07-31
(a) 1
2024-08-31
(a) 1
This is caused by
splitSpan _ (DayOfMonth dom) ds = splitspan (nthdayofmonthcontaining dom) (addGregorianMonthsToMonthday dom) 1 ds
Namely, nthdayofmonthcontaining shifts start date back to 30th:
nthdayofmonthcontaining :: MonthDay -> Day -> Day
nthdayofmonthcontaining mdy date
-- PARTIAL:
| not (validDay mdy) = error' $ "nthdayofmonthcontaining: invalid day " ++show mdy
| nthOfSameMonth <= date = nthOfSameMonth
| otherwise = nthOfPrevMonth
where nthOfSameMonth = nthdayofmonth mdy s
nthOfPrevMonth = nthdayofmonth mdy $ prevmonth s
s = startofmonth date
Note that splitSpan explicitly calls for this behavior, but I don't know why this behavior is desired:
-- | Split a DateSpan into consecutive exact spans of the specified Interval.
-- If the first argument is true and the interval is Weeks, Months, Quarters or Years,
-- the start date will be adjusted backward if needed to nearest natural interval boundary
-- (a monday, first of month, first of quarter or first of year).
The fix, i think, would be to filter the output of splitSpan here: https://github.com/simonmichael/hledger/blob/f001b23114c43776b31681b1bc5d85b0238a39d7/hledger-lib/Hledger/Data/PeriodicTransaction.hs#L233
and reject first returned subspans if they are from before the start of ptiterval
Assuming that there is no need/desire to change the behavior of splitSpan, I pushed a simple fix to periodic transaction generator (that is described above)
Thanks! I imagine the splitSpan behaviour was to support https://hledger.org/dev/hledger.html#date-adjustments . But that shifted a bit in the last year. Your fix may be all that's needed, I'll test a bit more as well.
I've pushed #2221, which fixes the start date in these cases:
- every Nth day of month from DATE with periodic transactions
- every M/D from DATE
- every M/D from DATE with periodic transactions
- every Nth WEEKDAY from DATE
and brings new docs and tests:
- https://hledger.org/dev/hledger.html#date-adjustments
- https://hledger.org/dev/hledger.html#period-headings
- https://github.com/simonmichael/hledger/blob/master/hledger/test/register/intervals.test#L140-L248
Fixed by #2221.