Generate contiguous price-interval schedules from a coerced URPX rate plan.
price-schedule walks a [start, end) instant window 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 full urpx.price resolved structure under
:urpx.interval/resolved. 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) instant window 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 full `urpx.price` resolved structure under
`:urpx.interval/resolved`. 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 zone)(price-schedule rate-plan start end zone opts)Generate a vector of merged price intervals across [start, end).
Each entry is: {:tick/beginning ZonedDateTime :tick/end ZonedDateTime :urpx.interval/resolved <full price/resolve-prices result>}
:tick/* are ZonedDateTimes in the resolved zone (callers wanting
plain Instants invoke .toInstant themselves). Adjacent steps with
identical ledger resolution are merged.
zone (a java.time.ZoneId) is optional when rate-plan declares
urpx:timezoneIdentifier; pass nil to use the plan's declared
timezone. An ex-info is thrown when neither is available.
Optional opts map:
: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 <full price/resolve-prices result>}
`:tick/*` are ZonedDateTimes in the resolved zone (callers wanting
plain Instants invoke `.toInstant` themselves). Adjacent steps with
identical ledger resolution are merged.
`zone` (a java.time.ZoneId) is optional when `rate-plan` declares
`urpx:timezoneIdentifier`; pass `nil` to use the plan's declared
timezone. An ex-info is thrown when neither is available.
Optional `opts` map:
: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 zone)(price-schedule-days rate-plan start days zone opts)Convenience: generate a price-schedule covering days days starting from
start. Accepts the same opts as price-schedule and the same
plan-or-explicit zone resolution.
Convenience: generate a `price-schedule` covering `days` days starting from `start`. Accepts the same `opts` as `price-schedule` and the same plan-or-explicit zone resolution.
(price-schedule-days-with-modifiers rate-plan modifiers start days)(price-schedule-days-with-modifiers rate-plan modifiers start days zone)(price-schedule-days-with-modifiers rate-plan modifiers start days zone opts)Convenience: generate a price-schedule-with-modifiers covering days
days starting from start. Same opts and zone resolution as
price-schedule-with-modifiers.
Convenience: generate a `price-schedule-with-modifiers` covering `days` days starting from `start`. Same `opts` and zone resolution as `price-schedule-with-modifiers`.
(price-schedule-with-modifiers rate-plan modifiers start end)(price-schedule-with-modifiers rate-plan modifiers start end zone)(price-schedule-with-modifiers rate-plan modifiers start end zone 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 merge-adjacent / step / zone-resolution semantics as
price-schedule. Same opts (:step, :holiday?, plus any other keys
that resolve-prices-with-modifiers consumes — e.g. URPX-vlf's
: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 merge-adjacent / step / zone-resolution semantics as `price-schedule`. Same `opts` (`:step`, `:holiday?`, plus any other keys that `resolve-prices-with-modifiers` consumes — e.g. URPX-vlf's `:profile-alternatives`).
(price-segments rate-plan modifiers start end)(price-segments rate-plan modifiers start end zone)(price-segments rate-plan modifiers start end zone 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, so the two are interchangeable at a
call site. 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.
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, so the two are interchangeable at a
call site. 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.
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 |