Generate contiguous price-interval schedules from a coerced URPX rate plan.
price-schedule walks a [start, end) window, bounded by two ZonedDateTimes
in any zone, in the rate plan's local timezone, calls
urpx.price/resolve-prices at each step, and merges adjacent steps whose
ledger resolutions are identical.
Output is a vector of interval maps each carrying :tick/beginning and
:tick/end (java.time.ZonedDateTime in the resolved zone — DST-correct
end-to-end) plus the urpx.price resolved structure under
:urpx.interval/resolved, keeping a season or TOU label only when it holds
for the whole interval. Callers that want plain java.time.Instant
values invoke .toInstant themselves at the call site.
Default step is 1 hour, anchored to the start-of-hour of start, so interior
boundaries fall on clock hours. Intervals are CLIPPED to the requested
window: the first begins at start and the last ends at end, however the
grid falls. Pass {:step (Duration/ofMinutes 15)} etc. for finer granularity
when a rate plan defines sub-hour TOU bracket transitions.
Generate contiguous price-interval schedules from a coerced URPX rate plan.
`price-schedule` walks a [start, end) window, bounded by two ZonedDateTimes
in any zone, in the rate plan's local timezone, calls
`urpx.price/resolve-prices` at each step, and merges adjacent steps whose
ledger resolutions are identical.
Output is a vector of interval maps each carrying `:tick/beginning` and
`:tick/end` (java.time.ZonedDateTime in the resolved zone — DST-correct
end-to-end) plus the `urpx.price` resolved structure under
`:urpx.interval/resolved`, keeping a season or TOU label only when it holds
for the whole interval. Callers that want plain `java.time.Instant`
values invoke `.toInstant` themselves at the call site.
Default step is 1 hour, anchored to the start-of-hour of `start`, so interior
boundaries fall on clock hours. Intervals are CLIPPED to the requested
window: the first begins at `start` and the last ends at `end`, however the
grid falls. Pass `{:step (Duration/ofMinutes 15)}` etc. for finer granularity
when a rate plan defines sub-hour TOU bracket transitions.(price-schedule rate-plan start end)(price-schedule rate-plan start end opts)Generate a vector of merged price intervals across [start, end).
Each entry is: {:tick/beginning ZonedDateTime :tick/end ZonedDateTime :urpx.interval/resolved <price/resolve-prices result>}
start and end are ZonedDateTimes in any zone. Their instants bound the
window; the walk happens in the plan's declared urpx:timezoneIdentifier,
and :tick/* are in that zone. A bound of any other type refuses
:urpx.schedule/bound-not-zoned-date-time. Adjacent steps with identical
ledger resolution are merged.
A merged interval carries :urpx.resolved/season-name,
:urpx.resolved/tou-period-name and :urpx.resolved/tou-period-number
only when that value holds for every step merged into it; a label that
changes inside the interval is omitted. The same holds for those keys on a
modifier ledger, which name the modifier's own season and period.
price-segments splits on those labels instead, so use it when they
matter.
A step whose resolution throws ExceptionInfo becomes an interval carrying
:urpx.interval/refused, the ex-data plus :message, in place of
:urpx.interval/resolved, and the walk continues. Adjacent refusals merge
when they differ only in temporal detail and message, as in
price-segments.
Optional opts map, refused as :urpx.schedule/opts-not-a-map when it is
anything else:
:step java.time.Duration — granularity at which the window is
walked. Default: (Duration/ofHours 1). Use a smaller
step for plans with sub-hour TOU bracket transitions.
:holiday? predicate (LocalDate -> bool) passed through to
urpx.price/resolve-prices.
Generate a vector of merged price intervals across `[start, end)`.
Each entry is:
{:tick/beginning ZonedDateTime
:tick/end ZonedDateTime
:urpx.interval/resolved <price/resolve-prices result>}
`start` and `end` are ZonedDateTimes in any zone. Their instants bound the
window; the walk happens in the plan's declared `urpx:timezoneIdentifier`,
and `:tick/*` are in that zone. A bound of any other type refuses
`:urpx.schedule/bound-not-zoned-date-time`. Adjacent steps with identical
ledger resolution are merged.
A merged interval carries `:urpx.resolved/season-name`,
`:urpx.resolved/tou-period-name` and `:urpx.resolved/tou-period-number`
only when that value holds for every step merged into it; a label that
changes inside the interval is omitted. The same holds for those keys on a
modifier ledger, which name the modifier's own season and period.
`price-segments` splits on those labels instead, so use it when they
matter.
A step whose resolution throws ExceptionInfo becomes an interval carrying
`:urpx.interval/refused`, the ex-data plus `:message`, in place of
`:urpx.interval/resolved`, and the walk continues. Adjacent refusals merge
when they differ only in temporal detail and message, as in
`price-segments`.
Optional `opts` map, refused as `:urpx.schedule/opts-not-a-map` when it is
anything else:
:step java.time.Duration — granularity at which the window is
walked. Default: `(Duration/ofHours 1)`. Use a smaller
step for plans with sub-hour TOU bracket transitions.
:holiday? predicate `(LocalDate -> bool)` passed through to
`urpx.price/resolve-prices`.(price-schedule-days rate-plan start days)(price-schedule-days rate-plan start days opts)Convenience: generate a price-schedule covering days calendar days in
the plan's zone starting from the ZonedDateTime start. Accepts the same
opts as price-schedule.
Convenience: generate a `price-schedule` covering `days` calendar days in the plan's zone starting from the ZonedDateTime `start`. Accepts the same `opts` as `price-schedule`.
(price-schedule-days-with-modifiers rate-plan modifiers start days)(price-schedule-days-with-modifiers rate-plan modifiers start days opts)Convenience: generate a price-schedule-with-modifiers covering days
calendar days in the plan's zone starting from the ZonedDateTime start.
Same opts as price-schedule-with-modifiers.
Convenience: generate a `price-schedule-with-modifiers` covering `days` calendar days in the plan's zone starting from the ZonedDateTime `start`. Same `opts` as `price-schedule-with-modifiers`.
(price-schedule-with-modifiers rate-plan modifiers start end)(price-schedule-with-modifiers rate-plan modifiers start end opts)Like price-schedule, but per step calls
urpx.price/resolve-prices-with-modifiers so each interval's
:urpx.interval/resolved includes the modifier ledgers appended to the
base plan's. Modifiers whose :urpx/applicableToRatePlan does not
include the base plan's @id are silently skipped (delegated behavior).
Same bounds, merge-adjacent, refusal and step semantics as
price-schedule. Same opts (:step, :holiday?, plus any other keys
that resolve-prices-with-modifiers consumes, such as
:profile-alternatives).
Like `price-schedule`, but per step calls `urpx.price/resolve-prices-with-modifiers` so each interval's `:urpx.interval/resolved` includes the modifier ledgers appended to the base plan's. Modifiers whose `:urpx/applicableToRatePlan` does not include the base plan's `@id` are silently skipped (delegated behavior). Same bounds, merge-adjacent, refusal and step semantics as `price-schedule`. Same `opts` (`:step`, `:holiday?`, plus any other keys that `resolve-prices-with-modifiers` consumes, such as `:profile-alternatives`).
(price-segments rate-plan modifiers start end)(price-segments rate-plan modifiers start end opts)A piecewise-constant price schedule across [start, end), with EXACT
boundaries derived from the documents rather than discovered by sampling.
Each entry is: {:tick/beginning ZonedDateTime :tick/end ZonedDateTime :urpx.interval/resolved <full price/resolve-prices result>}
the same shape price-schedule emits, except that every entry carries its
labels, so the two are interchangeable at a call site that reads prices.
The difference is where the boundaries fall: price-schedule
snaps them to its step grid, this puts them where the tariff actually
changes. For a client building a horizon and handing segments to an
optimizer, that is the difference between a schedule that is right and one
that is right only because every bracket in that plan happens to sit on an
hour.
Segments are merged on the FULL resolved value, not only on its ledgers: a change of TOU period name or season with identical prices is still a real boundary, and merging it away would leave the earlier value misstating the later part.
Takes modifiers so the composed result is segmented as one thing; pass an
empty collection for a base plan alone. Every document passed here is
harvested for candidate instants, so a version snapshot the caller did not
load cannot contribute a boundary; that is a property of what was supplied
rather than a limit of this function.
A resolution that THROWS - no version in effect at that instant, an
ambiguous version - becomes a segment carrying :urpx.interval/refused
with the ex-data, rather than aborting the window. Equal refusals merge, so
an uncovered stretch is one segment and not one per candidate.
Same bounds as price-schedule: ZonedDateTimes in any zone, segments in
the plan's. Optional opts are passed through to the resolver, and
:holiday? is worth supplying when the plan has no embedded calendar.
A piecewise-constant price schedule across `[start, end)`, with EXACT
boundaries derived from the documents rather than discovered by sampling.
Each entry is:
{:tick/beginning ZonedDateTime
:tick/end ZonedDateTime
:urpx.interval/resolved <full price/resolve-prices result>}
the same shape `price-schedule` emits, except that every entry carries its
labels, so the two are interchangeable at a call site that reads prices.
The difference is where the boundaries fall: `price-schedule`
snaps them to its step grid, this puts them where the tariff actually
changes. For a client building a horizon and handing segments to an
optimizer, that is the difference between a schedule that is right and one
that is right only because every bracket in that plan happens to sit on an
hour.
Segments are merged on the FULL resolved value, not only on its ledgers: a
change of TOU period name or season with identical prices is still a real
boundary, and merging it away would leave the earlier value misstating the
later part.
Takes `modifiers` so the composed result is segmented as one thing; pass an
empty collection for a base plan alone. Every document passed here is
harvested for candidate instants, so a version snapshot the caller did not
load cannot contribute a boundary; that is a property of what was supplied
rather than a limit of this function.
A resolution that THROWS - no version in effect at that instant, an
ambiguous version - becomes a segment carrying `:urpx.interval/refused`
with the ex-data, rather than aborting the window. Equal refusals merge, so
an uncovered stretch is one segment and not one per candidate.
Same bounds as `price-schedule`: ZonedDateTimes in any zone, segments in
the plan's. Optional `opts` are passed through to the resolver, and
`:holiday?` is worth supplying when the plan has no embedded calendar.cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |