Validate a date-parts value
Check a value from a parser before you store or convert it. This page shows the three ways to ask, and how to read the answer. The date-parts contract lists every rule a value is checked against.
Get every fault at once
validateParts() takes any argument and never throws. A valid value comes back with its recognized
components and its precision:
import { validateParts } from "@cosyte/dates";
validateParts({ year: 1988, month: 5, day: 7 }); // => { valid: true, parts: { year: 1988, month: 5, day: 7 }, precision: "day" }
An invalid value comes back with every fault, not only the first. Each issue names the component, the code of the rule it broke, and a message:
import { validateParts } from "@cosyte/dates";
const result = validateParts({ year: 88, month: 13, day: 40 });
result.valid; // => false
const faults = result.valid
? []
: result.issues.map((issue) => `${issue.component}: ${issue.code}`);
faults; // => ["year: year-not-four-digits", "month: out-of-range", "day: out-of-range"]
Branch on result.valid before you read parts or issues: TypeScript narrows the result to
ValidPartsResult or InvalidPartsResult on that check. Each code is listed, with what raises it,
in Errors and issue codes.
Use a type guard
isValidParts() is the same check as a boolean, and narrows an unknown to DateParts:
import { isValidParts } from "@cosyte/dates";
const fromParser: unknown = { year: 2024, month: 2, day: 29 };
// Inside the guard, fromParser is typed as DateParts.
const day = isValidParts(fromParser) ? fromParser.day : undefined;
day; // => 29
isValidParts({ year: 2025, month: 2, day: 29 }); // => false
Throw with the faults attached
assertValidParts() returns the recognized components, or throws a DatePartsError whose issues
are the same array validateParts() would return:
import { DatePartsError, assertValidParts } from "@cosyte/dates";
assertValidParts({ year: 1988, month: 5 }); // => { year: 1988, month: 5 }
let codes: string[] = [];
try {
assertValidParts({ year: 2025, month: 2, day: 29 });
} catch (error) {
if (error instanceof DatePartsError) codes = error.issues.map((issue) => issue.code);
}
codes; // => ["no-such-calendar-date"]
Every converter (toISO, toTemporal, toZonedDateTime, toInstant) and precisionOf validates
its argument the same way and throws the same DatePartsError, so you do not need to validate before
you convert. Validate first when you want to report the faults without a try.
Pass only the components the contract names
Validation reads year, month, day, hour, minute, second, fraction and offsetMinutes,
and nothing else. A property with any other name is ignored and left out of parts:
import { validateParts } from "@cosyte/dates";
const result = validateParts({
year: 2026,
month: 3,
day: 9,
hour: 8,
minute: 5,
millisecond: 250,
});
result.valid ? result.precision : undefined; // => "minute"
If your source holds sub-second time under another name, such as milliseconds, convert it to
fraction, a share of one second (250 milliseconds is 0.25), before you validate.
Log a fault without logging the date
Most messages quote only the component at fault and its value:
import { validateParts } from "@cosyte/dates";
const result = validateParts({ year: 1988, month: 13, day: 7 });
result.valid ? "" : result.issues[0]?.message; // => "month must be an integer in 1 to 12 (spec-native, January is 1, not 0); received the number 13"
A no-such-calendar-date message does not. It names the day, the month and the year, which is the
whole date:
import { validateParts } from "@cosyte/dates";
const result = validateParts({ year: 1988, month: 4, day: 31 });
result.valid ? "" : result.issues[0]?.message; // => "day 31 does not exist: April 1988 has 30 days"
The message of a DatePartsError joins its issues' messages, so it can carry the whole date too. A
date of birth is PHI. To log nothing from the value, log the component and code of each issue
and leave out the message.
Reference
validateParts,isValidParts,assertValidPartsandDatePartsErrorin the API reference.ValidationResultandValidationIssue, the shapes it returns.- The date-parts contract and Errors and issue codes.
- Precision explains why a fault is refused rather than repaired.