sourcelibs/Dates/src/Dates.xtlm
1⍝# Dates: its macro library -- d_ate<, date literals checked at compile time.
2⍝# Imported with the functions, under one alias: "d:" u_se< "Dates".
3⍝# A macro is a function from the source text written left and right of
4⍝# its call to the source that replaces the call, run before the program
5⍝# is compiled (X_eTaL MC10). Names with m: are macros; those under h: are
6⍝# private to this file.
7
8ᵈᵈ⁼u̲se< "Dates.xtl" ⍝ this library's functions, by path (MC23)
9
10digits ← ⎕D
11
12⍝## Parsing
13
14⍝# The text with each "-" as a space, so n_umbers reads the three parts.
15ʰs̲paced ← { t →
16 n ← t̲ally t
17 dash ← t = f̲irst "-"
18 ((r̲ange n) + dash × (n + 1) − r̲ange n) s̲elect t c̲at " "
19}
20
21⍝# Whether a text has the form yyyy-mm-dd (digits and two dashes).
22ʰf̲ormed? ← { t → (2 = t̲ally w̲here t = f̲irst "-") ∧ '∧ r̲/ t m̲ember? digits c̲at "-" }
23
24⍝# Whether y m d is a date of the calendar (Dates' own month lengths).
25ʰv̲alid? ← { ymd →
26 m ← f̲irst 1 d̲rop ymd
27 d ← f̲irst 2 d̲rop ymd
28 (m < 1) ∨ m > 12 ? 0 = 1
29 (d ≥ 1) ∧ d ≤ (f̲irst ymd) ᵈᵈd̲aysIn m
30}
31
32⍝## The macro
33
34⍝# @ d:d_ate< "2026-10-03": the date's day number, worked out when the
35⍝# program is compiled (20729), written in place of the call. A text
36⍝# that is not a date of the calendar (2026-02-30, 2026-13-01) stops the
37⍝# compiler at it: error[bad-date]. Nothing goes on the left (@).
38ᵐd̲ate< ← { none t →
39 ({ @ → 0 })_ none ⍝ the left side takes only @ (MC22)
40 n̲ot ʰf̲ormed? t ? "bad-date right" ⎕R̲EJECT t c̲at " is not a date: write it yyyy-mm-dd"
41 ymd ← f̲loor n̲umbers ʰs̲paced t
42 n̲ot ʰv̲alid? ymd ? "bad-date right" ⎕R̲EJECT t c̲at " is not a date of the calendar"
43 f̲ormat ᵈᵈd̲ays ymd
44}