///|
/// Materialize a closed range of calendar classifications.
pub fn CalendarTimeline::between(
calendar~ : Calendar,
start~ : Date,
end~ : Date,
) -> Result[CalendarTimeline, TimelineError] {
if start > end {
return Err(TimelineReversed)
}
let entries = Array::new()
let mut current = start
while true {
entries.push(calendar.query(current))
if current == end {
break
}
current = match current.try_add_days(1) {
Ok(value) => value
Err(_) => return Err(TimelineOutOfRange)
}
}
Ok({ entries, })
}
///|
/// Export one row per date for simple downstream ingestion.
pub fn CalendarTimeline::to_csv(self : CalendarTimeline) -> String {
let mut output = "date,kind,calendar,version\n"
for entry in self.entries {
output = output +
entry.date().to_string() +
"," +
entry.kind().to_string() +
"," +
entry.calendar_name() +
"," +
entry.calendar_version() +
"\n"
}
output
}
///|
/// Number of non-business days in the materialized range.
pub fn CalendarTimeline::closure_count(self : CalendarTimeline) -> Int {
self.closures().length()
}
///|
/// Business-day share formatted to two decimal places.
pub fn CalendarTimeline::business_day_ratio(self : CalendarTimeline) -> String {
let total = self.entries.length()
let business = self.business_days().length()
if total == 0 {
"0.00"
} else if business * 100 % total >= 50 {
((business * 100 / total + 1) / 100).to_string() +
"." +
((business * 100 / total + 1) % 100).to_string().pad_start(2, '0')
} else {
(business * 100 / total / 100).to_string() +
"." +
(business * 100 / total % 100).to_string().pad_start(2, '0')
}
}
///|
/// First materialized calendar entry.
pub fn CalendarTimeline::first(self : CalendarTimeline) -> CalendarDayInfo? {
if self.entries.is_empty() {
None
} else {
Some(self.entries[0])
}
}
///|
/// Last materialized calendar entry.
pub fn CalendarTimeline::last(self : CalendarTimeline) -> CalendarDayInfo? {
if self.entries.is_empty() {
None
} else {
Some(self.entries[self.entries.length() - 1])
}
}
///|
/// Render the timeline as a compact Markdown table.
pub fn CalendarTimeline::to_markdown(self : CalendarTimeline) -> String {
let mut output = "| date | kind | calendar | version |\n| --- | --- | --- | --- |\n"
for entry in self.entries {
output = output +
"| " +
entry.date().to_string() +
" | " +
entry.kind().to_string() +
" | " +
entry.calendar_name() +
" | " +
entry.calendar_version() +
" |\n"
}
output
}