Dates are the textbook case of Jev 1.13 jaggedness: the model reads "August 14" as text, not as an ordered quantity, so asking which date comes first or how far apart two dates are goes wrong – worse with mixed formats, "next Thursday", and domain boundaries like quarters. TypeSafe's date-extraction cookbook shows the fix that keeps working: seven Choice questions read the date's shape and parts off the text in one call; plain code turns the answers into a real date, counting from today for relative dates, with a confidence gate routing the weak reads to a human. This guide summarises the recipe with the key code shape.

You end up with one function, extract_date(document, role): hand it a document and a phrase like "the deadline to return the form", get back a date plus a confidence – or a flag saying no such date is stated, or a person should look at it.

The pattern: Choices for parts, code for calendars

Every part of a date is a small closed set – twelve months, thirty-one days, a bounded range of years – which makes extraction a Choice over enumerated options rather than free-form parsing, with an explicit "not stated" escape so a missing part is reported instead of guessed. The seven questions:

Code reads only the pieces mode calls for, assembles the date, and reports the lowest confidence among the parts it used – so one weak part sends the whole date to review. Anything under 0.60, or anything code cannot assemble at all, goes to a person; the rest go straight through.

The questions in code

def date_questions(role: str) -> dict[str, Choice]:
    """Seven typed choices that read a date's shape and parts off the text -- no math."""
    absent = "The document does not state this, or it is not this kind of date."
    return {
        "mode": Choice(
            instructions=(
                f"How is {role} written? 'absolute' = a calendar date naming a month; "
                "'relative' = relative to today; 'none' = the document does not state it."
            ),
            criteria={"absolute": None, "relative": None, "none": None},
        ),
        "month": Choice(
            instructions=f"If {role} is an absolute calendar date, which month is it in?",
            criteria={m: None for m in MONTHS} | {"none": absent},
        ),
        "day": Choice(
            instructions=f"If {role} is an absolute calendar date, which day (1-31)?",
            criteria={str(d): None for d in range(1, 32)} | {"none": absent},
        ),
        "year": Choice(
            instructions=(
                f"If {role} is an absolute calendar date, which year? 'none' if unstated "
                "(code infers it), 'out_of_range' if stated but off the list."
            ),
            criteria={str(y): None for y in YEAR_WINDOW}
            | {"out_of_range": "Stated but outside the listed range.",
               "none": "No year is stated."},
        ),
        "day_anchor": Choice(
            instructions=f"If {role} is relative to today, which day is it?",
            criteria={"today": None, "tomorrow": None, "day_after": None,
                      "weekday": None, "none": absent},
        ),
        "weekday": Choice(
            instructions=f"If {role} names a day of the week, which one?",
            criteria={w: None for w in WEEKDAYS} | {"none": absent},
        ),
        "week_offset": Choice(
            instructions=f"If {role} names a weekday, which week?",
            criteria={"current": None, "next": None, "none": absent},
        ),
    }

Resolve it in code

The assemble step is deliberately boring calendar math: fill in a missing year (current year, bumped to next only if the date is already more than a month past), map a named weekday to a date by a stated convention, reject impossible dates like February 30 as inconsistent reads. Both year inference and weekday resolution count from a pinned TODAY so relative dates reproduce on every run:

def extract_date(document: str, role: str) -> dict:
    return assemble(read_parts(document, role))  # one TypeSafe call, then pure code

Results on the demo set

Six questions over four short documents (contract, form, survey, review notice), resolved against a fixed Thursday. All six come out right:

QuestionExpectedGotConfFlags
Date the agreement takes effect2025-01-012025-01-010.97
Date the agreement expires2027-12-312027-12-310.91
Deadline to return the form2026-08-142026-08-140.95
Date of the kickoff callnonenone0.46review
Date the survey closes ("today")2026-07-302026-07-300.94
Date of the design review ("next Thursday")2026-08-062026-08-060.92

The interesting row is the kickoff call – a date the form never mentions. The model still returns absolute shape with no month to go with it, so the date comes back empty at 0.46 confidence, flagged for a person instead of hallucinated. Five auto-accept, one human review: that is the whole operating point.

Bottom line

Never ask Jev to do calendar math – ask it which boxes the text ticks, then do the math yourself. Choices over closed sets plus explicit "not stated" options plus weakest-link confidence is a reusable shape well beyond dates. Full source: TypeSafe's date-extraction cookbook; background on why dates are jagged in the Jev 1.13 jaggedness guide.