deadlines.ry
module deadlines
purpose: Find the tasks that are due soon and count the working days left for each.
import std.console
import std.time exposing Date, Weekday, InvalidDate
public type Task
purpose: Something to finish by a date.
has title: Text
has due: Date
can Compare by due
end
public type TaskError is one of
purpose: Why a task line could not be read.
MissingComma(line: Text)
end
public function parse_task(line: Text) returns Task or fails with TaskError or InvalidDate
purpose: Read a line of the form "title, 2024-05-10" into a task.
example: parse_task("report, 2024-05-10")
is Task(title: "report", due: Date(year: 2024, month: 5, day: 10))
example: parse_task("report") fails with MissingComma(line: "report")
example: parse_task("report, 2024-13-10") fails with InvalidDate(input: "2024-13-10")
let parts be line.split(",")
if parts.length() is not 2 then fail with MissingComma(line: line) end
let title be parts.at(0) otherwise fail with MissingComma(line: line)
let due_text be parts.at(1) otherwise fail with MissingComma(line: line)
let due be time.parse_date(due_text.trim()) otherwise fail
return Task(title: title.trim(), due: due)
end
function is_working_day(date: Date) returns Boolean
match date.weekday()
when Saturday then return false
when Sunday then return false
otherwise return true
end
end
public function working_days_between(start: Date, finish: Date) returns Integer
purpose: Count the Monday to Friday days after the start, up to and including the finish.
tags: dates, calendar
example: working_days_between(
start: Date(year: 2024, month: 5, day: 3),
finish: Date(year: 2024, month: 5, day: 6)
) is 1
example: working_days_between(
start: Date(year: 2024, month: 5, day: 6),
finish: Date(year: 2024, month: 5, day: 6)
) is 0
let mutable total be 0
let mutable current be start
repeat until current is at least finish
change current to current.plus_days(1)
if is_working_day(current) then change total to total + 1 end
end
return total
end
public function due_soon(tasks: List of Task, today: Date, within_days: Integer)
returns List of Task
purpose: Tasks due between today and the given number of days ahead, earliest first.
let limit be today.plus_days(within_days)
return for each task in tasks
where task.due is at least today and task.due is at most limit
sorted by task.due
collect task
end
public function main() needs console, time
purpose: Show which of the sample tasks are due within the next ten days.
let today be time.today()
let tasks be [
Task(title: "quarterly report", due: Date(year: 2026, month: 10, day: 9)),
Task(title: "renew certificate", due: Date(year: 2026, month: 11, day: 30)),
Task(title: "team review", due: Date(year: 2026, month: 10, day: 13))
]
for each task in due_soon(tasks: tasks, today: today, within_days: 10)
let remaining be working_days_between(start: today, finish: task.due)
console.print("{task.title}: due {task.due}, {remaining} working days left")
end
end