Credit Card Expiry Validation With Clock Injection
Parse MM/YY card expiry values, compare them against an injectable clock and report whether the card is valid through month end.
Code
export function parseExpiry(value) {
if (typeof value !== "string") throw new TypeError("expiry must be a string");
const match = /^(0[1-9]|1[0-2])\s*\/\s*(\d{2})$/.exec(value.trim());
if (!match) throw new RangeError("expiry must use MM/YY format");
const month = Number(match[1]);
const year = 2000 + Number(match[2]);
return { month, year };
}
export function isExpired(value, now = new Date()) {
const { month, year } = parseExpiry(value);
if (Number.isNaN(now.getTime())) throw new TypeError("now must be a valid Date");
const endOfMonth = new Date(Date.UTC(year, month, 1));
return now.getTime() >= endOfMonth.getTime();
}
export function validateExpiry(value, now = new Date()) {
const parsed = parseExpiry(value);
const expired = isExpired(value, now);
return {
valid: !expired,
reason: expired ? "expired" : null,
month: parsed.month,
year: parsed.year,
};
}Report a problem with this exampleOpens a pre-filled issue on GitHub.