Skip to content

Date calculations

The Dates and times page covers how Rhyme stores dates. This page covers the datefn set — the actions that do math and comparisons on those dates: adding days, counting the gap between two dates, formatting for display, and more.

Every datefn action returns a value — none of them change a variable in place. Always capture the result with $result = .

Adding and subtracting time

ActionWhat it doesExample
add-daysAdds (or subtracts) a number of days$due = add-days 10 to $start-date
add-weeksAdds (or subtracts) a number of weeks$due = add-weeks 2 to $start-date
add-monthsAdds (or subtracts) a number of months$due = add-months 3 to $start-date
add-yearsAdds (or subtracts) a number of years$due = add-years 5 to $start-date

Each takes a count and a date, connected with to:

$start-date = "2025-01-01"
$due = add-days 10 to $start-date
// $due is "2025-01-11"
$renewal = add-years 5 to $start-date
// $renewal is "2030-01-01"

To subtract, use a negative number — but put it in a variable first, since a bare negative literal isn’t accepted here:

$due-date = "2025-01-01"
$days-back = -5
$reminder-date = add-days $days-back to $due-date
// $reminder-date is "2024-12-27"

Comparing and counting dates

ActionWhat it doesExample
days-betweenNumber of days from one date to another$gap = days-between $start-date and $end-date
days-untilNumber of days from today until a date$countdown = days-until $target-date
date-afterWhether the first date is strictly after the second$later = date-after $date-a $date-b
date-beforeWhether the first date is strictly before the second$earlier = date-before $date-a $date-b
date-betweenWhether today falls within a date range (inclusive)$in-range = date-between $range-start and $range-end
$start-date = "2025-01-01"
$end-date = "2025-01-31"
$gap = days-between $start-date and $end-date
// $gap is 30 — order matters: reversing the dates gives a negative number
$target = "2030-06-15"
$countdown = days-until $target

date-after and date-before take two dates with no connecting word, and are strict — equal dates return false:

$date-a = "2025-12-31"
$date-b = "2025-01-01"
$later = date-after $date-a $date-b
// $later is true

date-between is easy to misread — despite the name, it doesn’t compare two arbitrary dates. It always checks whether today falls inside the given range:

$range-start = "2020-01-01"
$range-end = "2030-12-31"
$in-range = date-between $range-start and $range-end
// true if today is anywhere from 2020-01-01 through 2030-12-31, inclusive

Both today and any of these actions accept the literal word today in place of a date variable, e.g. days-until today or date-after today $deadline.

Reading parts of a date

ActionWhat it doesExample
get-dayDay of the month (1–31)$d = get-day from $date
get-monthMonth number (1–12)$m = get-month from $date
get-yearFour-digit year$y = get-year from $date
ageWhole years since a birthdate, as of today$years = age $birthdate
day-namesThe 7 weekday names, Monday first$weekdays = day-names
month-namesThe 12 month names$months = month-names
$sample = "2025-11-14"
$day-of-month = get-day from $sample
$month-num = get-month from $sample
$year-num = get-year from $sample
// 14, 11, 2025
$age-years = age "2000-01-01"

day-names and month-names take no arguments — they just return the list, localized to the user’s language:

$weekday-names = day-names
// ["Monday", "Tuesday", ..., "Sunday"]

Formatting and parsing

format-date turns a date into a display string using a template — YYYY for the year, MM for the month, DD for the day:

$sample = "2025-11-14"
$display = format-date $sample as "MM/DD/YYYY"
// "11/14/2025"

parse-date is the reverse: turn a display string into Rhyme’s standard date format, given the template it was written in:

$parsed = parse-date "6/20/13" from "M/D/YY"
// "2013-06-20"

relative-time gives a human-friendly description of a date relative to today:

$relative = relative-time today
// "today"

Finding the start and end of a period

ActionWhat it does
start-of-month / end-of-monthFirst / last day of the date’s month
start-of-week / end-of-weekMonday / Sunday of the date’s week
start-of-year / end-of-yearJanuary 1 / December 31 of the date’s year
$mid-month = "2025-06-15"
$month-start = start-of-month $mid-month
$month-end = end-of-month $mid-month
// "2025-06-01", "2025-06-30"
$week-anchor = "2025-06-18"
$week-start = start-of-week $week-anchor
$week-end = end-of-week $week-anchor
// "2025-06-16" (Monday), "2025-06-22" (Sunday)

If the date given is already the start or end of that period, these return the same date unchanged — calling end-of-week on a Sunday just returns that Sunday.

Handling missing results

Like the math actions, a datefn action given a missing or invalid date produces no value instead of an error. Check with if missing:

$event-date = "2026-12-25"
$days-left = days-until $event-date
if missing $days-left:
.text "No event date set" #red
:else
.text "Days until the event: {$days-left}" -bold
:end

Complete example: billing period and reminder

$due = "2026-09-01"
$reminder-lead = -7
$reminder-date = add-days $reminder-lead to $due
.text "Reminder starts: {$reminder-date}"
$billing-anchor = "2026-03-14"
$period-start = start-of-month $billing-anchor
$period-end = end-of-month $billing-anchor
.text "Billing period: {$period-start} to {$period-end}"