Add period-completeness helpers#16
Merged
Merged
Conversation
Provides a shared, business-day-aware toolkit for reporting on partial periods, replacing logic that was re-implemented per project. `period_is_complete()` tests whether the period (week/month/quarter/ year) containing each date is complete as of a cutoff, using a QuantLib calendar (default "WeekendsOnly"; "UnitedStates" for holiday accuracy; "Null" for pure calendar-day semantics). Also adds `period_start_date()`/`period_end_date()` (canonical calendar boundaries), `filter_complete_periods()` (drops the in-progress trailing period; as_of defaults to the data max and an earlier as_of is an error), `last_complete_period_start()`/`last_complete_period_end()`, and `scale_alpha_logical()` for fading incomplete periods in ggplots. Completeness is judged on business days only; returned dates are always canonical calendar boundaries. NA dates propagate to NA and are dropped by filter_complete_periods(). Vectorizes correctly over a span of dates. Co-Authored-By: Claude Opus 4.8 <[email protected]>
mcaselli
force-pushed
the
feature/period-completeness
branch
from
July 14, 2026 18:58
e9ad12f to
714ba21
Compare
Restrict the period-completeness family to week/month/quarter/year. "day" had no real use case here: the boundary functions are no-ops for it (start and end both equal the input date), and business-day completeness produces misleading results for single days (a Sunday reads complete as of the preceding Saturday). "Is a day complete" is just date <= as_of and needs none of this machinery. Invalid units, including "day", now error via validate_period_unit(). Co-Authored-By: Claude Opus 4.8 <[email protected]>
Add a "Period completeness" section covering period_start_date()/ period_end_date(), period_is_complete(), the scale_alpha_logical() alpha-fade for in-progress periods, filter_complete_periods(), and last_complete_period_end()/start(), worked through example_sales (whose final month is partial). Bridges from the existing dashed-final-period behavior of plot_accounts_by_status(). Scale back the business-day-of-period burn-up section: replace the by-market faceted example (a near-duplicate of the global one) with a one-line pointer, to keep the vignette focused. Co-Authored-By: Claude Opus 4.8 <[email protected]>
The monthly example passed as_of = max(order_date) to period_is_complete(),
silently duplicating filter_complete_periods()'s default cutoff and
obscuring which behavior is the default. Restructure as a two-part
example: first filter_complete_periods() with defaults (December, still
in progress, drops out), then a counter-example supplying an as_of in
the next period ("data complete through January 1") so the trailing
month counts as complete. The alpha-fade chart now states it reuses that
same latest-date cutoff. Also correct the note that period_is_complete()
defaults as_of to the current date.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Replace the filter_complete_periods() summaries with the more transparent group_by(month) |> summarise() style, in two pieces. The first omits as_of, so completeness is judged as of today and every historical month (including the partial December) reads complete; the second passes as_of = latest order date and a UnitedStates holiday calendar, correctly flagging December incomplete. Each summary shows month, units, last_order_in_period, and complete, making the reasoning visible. filter_complete_periods() is kept as a brief row-filter shortcut. Co-Authored-By: Claude Opus 4.8 <[email protected]>
period_is_complete(), last_complete_period_start(), and last_complete_period_end() no longer default as_of to the current date. Completeness is a data-currency judgment, so silently keying it off Sys.Date() misreads cached/stale data (e.g. marking a past-but- partial month complete). Callers now state the reference explicitly; pass Sys.Date() to opt into wall-clock. filter_complete_periods() is unchanged (still defaults as_of to the max of its date column). For a consistent temporal-helper surface, rename most_recent_monday() / most_recent_sunday()'s ref_date argument to as_of (same concept: the date state is evaluated as of). Their current-date default is kept; positional calls are unaffected, only named ref_date = callers. Vignette recast to two references (wall-clock vs latest data date); tests added for the required-as_of errors and the as_of argument. Co-Authored-By: Claude Opus 4.8 <[email protected]>
Drop the design-decision prose and the two inert examples (Sys.Date() where everything reads complete, and a UnitedStates calendar that changed nothing at as_of = 2024-12-20). Replace with examples whose output visibly reflects the argument shown: a vector as_of returning TRUE/TRUE/FALSE, and a holiday example on the July-4th work week where "UnitedStates" reports complete but "WeekendsOnly" does not. Co-Authored-By: Claude Opus 4.8 <[email protected]>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a shared, business-day-aware period-completeness toolkit, and aligns the existing
most_recent_*helpers with it.New functions
period_is_complete(date, unit, as_of, calendar, week_start)— is the period (week/month/quarter/year) containing each date complete as of the cutoffas_of? A period is complete once no business days remain afteras_ofup to and including the period end, evaluated in a QuantLib calendar.calendar = "WeekendsOnly"(default): complete once only weekends remain."UnitedStates"): holiday-accurate.calendar = "Null": pure calendar-day semantics (period_end_date(date) <= as_of).period_start_date()/period_end_date()— canonical first/last calendar day of the period. Business-day calendars only ever inform completeness, never the returned dates.filter_complete_periods(data, date_col, ...)— keep only rows whose period is complete;as_ofdefaults tomax(date_col)so completeness tracks how current the data is.last_complete_period_start()/last_complete_period_end()— boundaries of the most recent complete period as of a cutoff.scale_alpha_logical()— ggplot2 alpha scale to fade the in-progress period; pairs withperiod_is_complete().as_ofhas no wall-clock defaultperiod_is_complete()andlast_complete_period_*()require an explicitas_of— there is noSys.Date()default. Completeness is a data-currency judgment, and this work runs mostly on cached extracts, so silently keying off the wall clock would misread stale data (e.g. marking a past-but-partial month complete). PassSys.Date()to opt into wall-clock behaviour.filter_complete_periods(), which sees the data frame, defaultsas_oftomax(date_col).max(date)is deliberately not a default forperiod_is_complete(): itsdateargument is frequently period anchors fromgroup_by(month = period_start_date(...)), where the max is the latest bucket start, not how current the data is.Behaviour change:
most_recent_*most_recent_monday()/most_recent_sunday()'sref_dateargument is renamedas_of, for a consistent reference-date name across the temporal helpers (both name the date that state is evaluated as of). Their current-date default is unchanged and positional calls are unaffected — only callers passingref_date =by name need to switch toas_of =.Notes
qlcalengine (bizdays_between()) and calendar scoping.week_startdefaults togetOption("lubridate.week.start", 7)so the package defers to the session's week convention.datespan (a fix over a prior implementation that mis-judged future periods whenas_ofsat on its own period's last business day)."UnitedStates"reports the week complete but the default"WeekendsOnly"does not.Tests
test-period_completeness.R(33test_thatblocks) covers weekend/holiday month-end edges,as_ofon the period end,"Null"equivalence, the vectorization regression,last_complete_period_*step-back,filter_complete_periodsdefault / guardedas_of, required-as_oferrors,NApropagation, leap-February, year-end, andweek_start; plus a named-as_oftest formost_recent_*. Full suite: 275 pass, 0 failures, 0 warnings.R CMD check: 0 errors, 0 warnings (2 environmental NOTEs).