Date & Time Module¶
The date_time standard library module provides relational predicates for constructing, decomposing, and manipulating dates and times. All predicates work with real Python datetime objects — not custom term types.
The implementation lives in clausal/modules/date_time.py.
Import¶
-import_from(date_time, [Now, Today, Date, Time, DateTime,
TimeDelta, DateAdd, DateSub, DateDiff,
DaysBetween, FormatDate, ParseDate,
DateOf, DayOfWeek, DateBetween])
Or via module import:
Python Interop¶
All predicates produce and consume standard Python objects:
| Predicate | Python type |
|---|---|
Date/4 |
datetime.date |
Time/4 |
datetime.time |
DateTime/7 |
datetime.datetime |
TimeDelta/3 |
datetime.timedelta |
Unification uses Python's native ==. Any datetime method can be called via ++() interop:
-import_from(date_time, [Date, FormatDate])
IsoDate(Y, M, D, S) <- (
Date(Y, M, D, DT),
S is ++DT.isoformat()
)
Prefer the declarative predicates over ++ escapes
++() drops into arbitrary Python and is reserved for last-resort interop. The common date operations all have clean, relational equivalents — reach for these first:
Instead of ++ … |
Use |
|---|---|
S is ++DT.isoformat() |
FormatDate(DT, "%Y-%m-%d", S) |
N is ++TD.days |
TimeDelta(N, _, TD) |
D is ++DT.date() |
DateOf(DT, D) |
DateDiff(A, B, TD), N is ++TD.days |
DaysBetween(A, B, N) |
Predicates¶
Now/1, NowUTC/1, Today/1¶
Now(DT) # DT = datetime.datetime.now()
NowUTC(DT) # DT = datetime.datetime.now(UTC)
Today(D) # D = datetime.date.today()
Date/4 — Bidirectional¶
Date(Year, Month, Day, DateObj) — construct or decompose:
# Construct
Date(2026, 3, 16, D) # D = datetime.date(2026, 3, 16)
# Decompose
Date(Y, M, D, SomeDateObj) # Y, M, D bound to components
Time/4 — Bidirectional¶
Time(Hour, Minute, Second, TimeObj):
DateTime/7 — Bidirectional¶
DateTime(Year, Month, Day, Hour, Minute, Second, DtObj):
TimeDelta/3 — Bidirectional¶
TimeDelta(Days, Seconds, TdObj):
TimeDelta(7, 0, TD) # TD = datetime.timedelta(days=7)
TimeDelta(D, S, TD) # decompose TD into days and seconds
DateAdd/3, DateSub/3¶
DateAdd(DATE, DELTA, RESULT) # RESULT = DATE + DELTA
DateSub(DATE, DELTA, RESULT) # RESULT = DATE - DELTA
DateDiff/3¶
DaysBetween/3¶
DaysBetween(DateA, DateB, N) — the whole-day count of DateA - DateB as a plain integer, so the common "days between two dates" need is a single goal instead of DateDiff(A, B, TD), TimeDelta(N, _, TD):
FormatDate/3¶
ParseDate/3¶
DateOf/2 — Bidirectional¶
DateOf(DateTime, Date) — the declarative form of ++DT.date(). Forward, it extracts the calendar datetime.date from a datetime.datetime; in reverse (with DateTime unbound) it builds the midnight datetime of a datetime.date:
DateOf(DT, D) # D = DT.date() (datetime → date)
DateOf(DT, D) # DT = midnight of D (date → datetime; DT unbound)
DayOfWeek/2¶
DateBetween/3 — Nondeterministic¶
DateBetween(Start, End, D) — generates each date in the range [Start, End]:
This is nondeterministic — it succeeds once for each date in the range via backtracking.
Test coverage
Tests are in tests/test_date_time.py.
- Now/NowUTC/Today: current timestamps
- Date/4: construct, decompose, invalid values
- Time/4: construct, decompose
- DateTime/7: construct, decompose
- TimeDelta/3: construct, decompose
- DateAdd/DateSub/DateDiff: arithmetic
- DaysBetween: direct integer day count
- FormatDate/ParseDate: strftime/strptime
- DateOf: datetime ↔ date (both modes)
- DayOfWeek: weekday computation
- DateBetween: date range enumeration
See also: I/O — writing and formatting output · Python Interop — ++() escape for additional datetime operations.