hledger-lib-1.51.1: A library providing the core functionality of hledger
Safe HaskellNone
LanguageGHC2021

Hledger.Data.DayPartition

Description

A partition of time into contiguous spans, for defining reporting periods.

Synopsis

Documentation

data DayPartition Source #

A partition of time into one or more contiguous periods, plus a historical period that precedes them. Note DayPartition does not store per-period data - only the periods' start/end dates.

constructors

boundariesToDayPartition :: NonEmpty Day -> DayPartition Source #

Construct a DayPartition from a non-empty list of period boundary dates (start dates plus a final exclusive end date).

>>> boundariesToDayPartition (fromGregorian 2025 01 01 :| [fromGregorian 2025 02 01])
DayPartition {dayPartitionToPeriodData = PeriodData{ pdpre = 2024-12-31, pdperiods = fromList [(2025-01-01,2025-01-31)]}}

boundariesToMaybeDayPartition :: [Day] -> Maybe DayPartition Source #

Construct a DayPartition from a list of period boundary dates (start dates plus a final exclusive end date), if it's a non-empty list.

conversions

dayPartitionToNonEmpty :: DayPartition -> NonEmpty (Day, Day) Source #

Convert DayPartition to a non-empty list of period start and end dates (both inclusive). Each end date will be one day before the next period's start date.

dayPartitionToList :: DayPartition -> [(Day, Day)] Source #

Convert DayPartition to a list (which will always be non-empty) of period start and end dates (both inclusive). Each end date will be one day before the next period's start date.

dayPartitionToDateSpans :: DayPartition -> [DateSpan] Source #

Convert DayPartition to a list of DateSpans. Each span will end one day before the next span begins (the span's exclusive end date will be equal to the next span's start date).

operations

unionDayPartitions :: DayPartition -> DayPartition -> Maybe DayPartition Source #

Return the union of two DayPartitions if that is a valid DayPartition, or Nothing otherwise.

dayPartitionStartEnd :: DayPartition -> (Day, Day) Source #

Get this DayPartition's overall start date and end date (both inclusive).

dayPartitionFind :: Day -> DayPartition -> (Maybe Day, Day) Source #

Find the start and end dates of the period within a DayPartition which contains a given day. If the day is after the end of the last period, it is assumed to be within the last period. If the day is before the start of the first period (ie, in the historical period), only the historical period's end date is returned.

splitSpan :: Bool -> Interval -> DateSpan -> Maybe DayPartition Source #

Split a DateSpan into a DayPartition consisting of consecutive exact spans of the specified Interval, or Nothing if the span is invalid. If no interval is specified, the original span is returned. If the original span is the null date span, ie unbounded, Nothing is returned. If the original span is empty, eg if the end date is <= the start date, Nothing is returned.

Date adjustment

Some intervals respect the "adjust" flag (years, quarters, months, weeks, every Nth weekday of month seem to be the ones that need it). This will move the start date earlier, if needed, to the previous natural interval boundary (first of year, first of quarter, first of month, monday, previous Nth weekday of month). Related: #1982 #2218

The end date is always moved later if needed to the next natural interval boundary, so that the last period is the same length as the others.

Examples

>>> let t i y1 m1 d1 y2 m2 d2 = fmap dayPartitionToNonEmpty . splitSpan True i $ DateSpan (Just $ Flex $ fromGregorian y1 m1 d1) (Just $ Flex $ fromGregorian y2 m2 d2)
>>> t NoInterval 2008 01 01 2009 01 01
Just ((2008-01-01,2008-12-31) :| [])
>>> t (Quarters 1) 2008 01 01 2009 01 01
Just ((2008-01-01,2008-03-31) :| [(2008-04-01,2008-06-30),(2008-07-01,2008-09-30),(2008-10-01,2008-12-31)])
>>> splitSpan True (Quarters 1) nulldatespan
Nothing
>>> t (Days 1) 2008 01 01 2008 01 01  -- an empty datespan
Nothing
>>> t (Quarters 1) 2008 01 01 2008 01 01
Nothing
>>> t (Months 1) 2008 01 01 2008 04 01
Just ((2008-01-01,2008-01-31) :| [(2008-02-01,2008-02-29),(2008-03-01,2008-03-31)])
>>> t (Months 2) 2008 01 01 2008 04 01
Just ((2008-01-01,2008-02-29) :| [(2008-03-01,2008-04-30)])
>>> t (Weeks 1) 2008 01 01 2008 01 15
Just ((2007-12-31,2008-01-06) :| [(2008-01-07,2008-01-13),(2008-01-14,2008-01-20)])
>>> t (Weeks 2) 2008 01 01 2008 01 15
Just ((2007-12-31,2008-01-13) :| [(2008-01-14,2008-01-27)])
>>> t (MonthDay 2) 2008 01 01 2008 04 01
Just ((2008-01-02,2008-02-01) :| [(2008-02-02,2008-03-01),(2008-03-02,2008-04-01)])
>>> t (NthWeekdayOfMonth 2 4) 2011 01 01 2011 02 15
Just ((2010-12-09,2011-01-12) :| [(2011-01-13,2011-02-09),(2011-02-10,2011-03-09)])
>>> t (DaysOfWeek [2]) 2011 01 01 2011 01 15
Just ((2010-12-28,2011-01-03) :| [(2011-01-04,2011-01-10),(2011-01-11,2011-01-17)])
>>> t (MonthAndDay 11 29) 2012 10 01 2013 10 15
Just ((2012-11-29,2013-11-28) :| [])

intervalBoundaryBefore :: Interval -> Day -> Day Source #

Get the natural start for the given interval that falls on or before the given day, when applicable. Works for Weeks, Months, Quarters, Years, eg.

tests