hledger-lib-1.21: A reusable library providing the core functionality of hledger
Safe HaskellNone
LanguageHaskell2010

Hledger.Data.PeriodicTransaction

Description

A PeriodicTransaction is a rule describing recurring transactions.

Synopsis

Documentation

runPeriodicTransaction :: PeriodicTransaction -> DateSpan -> [Transaction] Source #

Generate transactions from PeriodicTransaction within a DateSpan

Note that new transactions require txnTieKnot post-processing. The new transactions will have three tags added: - a recur:PERIODICEXPR tag whose value is the generating periodic expression - a generated-transaction: tag - a hidden _generated-transaction: tag which does not appear in the comment.

>>> import Data.Time (fromGregorian)
>>> _ptgen "monthly from 2017/1 to 2017/4"
2017-01-01
    ; generated-transaction: ~ monthly from 2017/1 to 2017/4
    a           $1.00

2017-02-01
    ; generated-transaction: ~ monthly from 2017/1 to 2017/4
    a           $1.00

2017-03-01
    ; generated-transaction: ~ monthly from 2017/1 to 2017/4
    a           $1.00

>>> _ptgen "monthly from 2017/1 to 2017/5"
2017-01-01
    ; generated-transaction: ~ monthly from 2017/1 to 2017/5
    a           $1.00

2017-02-01
    ; generated-transaction: ~ monthly from 2017/1 to 2017/5
    a           $1.00

2017-03-01
    ; generated-transaction: ~ monthly from 2017/1 to 2017/5
    a           $1.00

2017-04-01
    ; generated-transaction: ~ monthly from 2017/1 to 2017/5
    a           $1.00

>>> _ptgen "every 2nd day of month from 2017/02 to 2017/04"
2017-01-02
    ; generated-transaction: ~ every 2nd day of month from 2017/02 to 2017/04
    a           $1.00

2017-02-02
    ; generated-transaction: ~ every 2nd day of month from 2017/02 to 2017/04
    a           $1.00

2017-03-02
    ; generated-transaction: ~ every 2nd day of month from 2017/02 to 2017/04
    a           $1.00

>>> _ptgen "every 30th day of month from 2017/1 to 2017/5"
2016-12-30
    ; generated-transaction: ~ every 30th day of month from 2017/1 to 2017/5
    a           $1.00

2017-01-30
    ; generated-transaction: ~ every 30th day of month from 2017/1 to 2017/5
    a           $1.00

2017-02-28
    ; generated-transaction: ~ every 30th day of month from 2017/1 to 2017/5
    a           $1.00

2017-03-30
    ; generated-transaction: ~ every 30th day of month from 2017/1 to 2017/5
    a           $1.00

2017-04-30
    ; generated-transaction: ~ every 30th day of month from 2017/1 to 2017/5
    a           $1.00

>>> _ptgen "every 2nd Thursday of month from 2017/1 to 2017/4"
2016-12-08
    ; generated-transaction: ~ every 2nd Thursday of month from 2017/1 to 2017/4
    a           $1.00

2017-01-12
    ; generated-transaction: ~ every 2nd Thursday of month from 2017/1 to 2017/4
    a           $1.00

2017-02-09
    ; generated-transaction: ~ every 2nd Thursday of month from 2017/1 to 2017/4
    a           $1.00

2017-03-09
    ; generated-transaction: ~ every 2nd Thursday of month from 2017/1 to 2017/4
    a           $1.00

>>> _ptgen "every nov 29th from 2017 to 2019"
2016-11-29
    ; generated-transaction: ~ every nov 29th from 2017 to 2019
    a           $1.00

2017-11-29
    ; generated-transaction: ~ every nov 29th from 2017 to 2019
    a           $1.00

2018-11-29
    ; generated-transaction: ~ every nov 29th from 2017 to 2019
    a           $1.00

>>> _ptgen "2017/1"
2017-01-01
    ; generated-transaction: ~ 2017/1
    a           $1.00

>>> _ptgen ""
*** Exception: failed to parse...
...
>>> _ptgen "weekly from 2017"
*** Exception: Unable to generate transactions according to "weekly from 2017" because 2017-01-01 is not a first day of the Week
>>> _ptgen "monthly from 2017/5/4"
*** Exception: Unable to generate transactions according to "monthly from 2017/5/4" because 2017-05-04 is not a first day of the Month
>>> _ptgen "every quarter from 2017/1/2"
*** Exception: Unable to generate transactions according to "every quarter from 2017/1/2" because 2017-01-02 is not a first day of the Quarter
>>> _ptgen "yearly from 2017/1/14"
*** Exception: Unable to generate transactions according to "yearly from 2017/1/14" because 2017-01-14 is not a first day of the Year
>>> let reportperiod="daily from 2018/01/03" in let (i,s) = parsePeriodExpr' nulldate reportperiod in runPeriodicTransaction (nullperiodictransaction{ptperiodexpr=reportperiod, ptspan=s, ptinterval=i, ptpostings=["a" `post` usd 1]}) (DateSpan (Just $ fromGregorian 2018 01 01) (Just $ fromGregorian 2018 01 03))
[]
>>> _ptgenspan "every 3 months from 2019-05" (DateSpan (Just $ fromGregorian 2020 01 01) (Just $ fromGregorian 2020 02 01))
>>> _ptgenspan "every 3 months from 2019-05" (DateSpan (Just $ fromGregorian 2020 02 01) (Just $ fromGregorian 2020 03 01))
2020-02-01
    ; generated-transaction: ~ every 3 months from 2019-05
    a           $1.00

>>> _ptgenspan "every 3 days from 2018" (DateSpan (Just $ fromGregorian 2018 01 01) (Just $ fromGregorian 2018 01 05))
2018-01-01
    ; generated-transaction: ~ every 3 days from 2018
    a           $1.00

2018-01-04
    ; generated-transaction: ~ every 3 days from 2018
    a           $1.00

>>> _ptgenspan "every 3 days from 2018" (DateSpan (Just $ fromGregorian 2018 01 02) (Just $ fromGregorian 2018 01 05))
2018-01-04
    ; generated-transaction: ~ every 3 days from 2018
    a           $1.00

checkPeriodicTransactionStartDate :: Interval -> DateSpan -> Text -> Maybe String Source #

Check that this date span begins at a boundary of this interval, or return an explanatory error message including the provided period expression (from which the span and interval are derived).

Orphan instances