Pub Version Pub Points Package checks License: BSD-3-Clause

minted_chronology

Calendar dates and durations as well-modelled value types.

Part of the minted family: pure-Dart value types built on parse, don't validate, so the parser is the only door in and anything that came through it is well-formed by construction. Once you hold a Date, it is a real calendar date.

Install

dart pub add minted_chronology

minted comes with it, holding the shared vocabulary (ParseOutcome, MintedFailure, Digit, Digits, the Uint tower). Nothing here drags in another domain's engine.

What's in the box

Type What it guarantees Standard
Date a real calendar date: no time, no zone; impossible dates rejected ISO 8601
Month a real month 1-12 that knows its own length (leap-aware) building block
Weekday one of seven named days, ISO-numbered 1 (Monday) to 7 (Sunday) ISO 8601
Iso8601Duration a duration with months and years, which dart:core Duration cannot hold ISO 8601

Date is the type DateTime isn't: no clock, no zone, and an impossible date is refused rather than rolled over. Weekday is an enum a Date hands back, so a switch over one needs no default arm.

A quick taste

final date = Date.tryParse('2026-07-07')!;   // strict ISO 8601 YYYY-MM-DD
date.iso8601;             // '2026-07-07'   (canonical form)
date.weekday;             // Weekday.tuesday   (.value is 2, matching DateTime.weekday)
date.month.daysIn(2026);  // 31   (the month is a Month, and knows its length)
date.tryAddDays(30);      // Date(2026-08-06)
date.tryAddDays(3000000); // null   (the walk left the 0000-9999 bound)
Date.now();               // today in the local zone, the date-only DateTime.now()

// impossible dates are rejected, not rolled over the way DateTime does:
Date.tryParse('2026-13-01');   // null (no 13th month; DateTime would give 2027-01-01)

// Weekday arithmetic wraps round the week, and bridges back from dart:core:
date.weekday.next;                         // Weekday.wednesday
Weekday.friday.daysUntil(Weekday.monday);  // 3
Weekday.tryFrom(DateTime.now().weekday);   // a Weekday, or null

// Iso8601Duration holds components, because a month has no length until anchored to a date:
final span = Iso8601Duration.tryParse('P1Y2M3DT4H')!;
span.months;                                        // 2
span.toDuration(from: Date.of(2026, 1, 31).getOrThrow());  // 427 days and 4 hours
Iso8601Duration.tryParse('PT1M')!.iso8601;          // 'PT1M'   (a minute; P1M is a month)
Iso8601Duration.tryParse('P1Y2W');                  // null: the week form never mixes

The runnable version is the example.

One shape, every type

  • Type.tryParse(input) hands back the value, or null when the input isn't valid
  • Type.parse(input) hands back a ParseOutcome: the value, or a typed failure (DateFailure, MonthFailure, Iso8601DurationFailure) you can switch on, or read as a form-field message via .reasonOrNull. No door throws
  • value equality, a canonical .iso8601, chronological ordering (<, isBefore, compareTo), and Date.of / Date.fromDateTime for parts you already hold
  • Weekday is a classification rather than a parsed value, so it takes tryFrom(isoDayNumber) instead of a parse door

The minted README is the family guide: the whole catalogue, handling failures, and the one caveat (never cast into a minted type).

Libraries

minted_chronology
Calendar dates and durations as well-modelled value types.