UNPKG

@formatjs/intl-datetimeformat

Version:
91 lines (90 loc) 3.11 kB
import { invariant } from "@formatjs/ecma402-abstract"; import { DATE_TIME_PROPS, additionPenalty, removalPenalty, longMorePenalty, shortMorePenalty, shortLessPenalty, longLessPenalty, offsetPenalty } from "./utils.js"; /** * https://tc39.es/ecma402/#sec-basicformatmatcher * @param options * @param formats */ export function BasicFormatMatcher(options, formats) { let bestScore = -Infinity; let bestFormat = formats[0]; invariant(Array.isArray(formats), "formats should be a list of things"); for (const format of formats) { let score = 0; for (const prop of DATE_TIME_PROPS) { const optionsProp = options[prop]; const formatProp = format[prop]; if (optionsProp === undefined && formatProp !== undefined) { score -= additionPenalty; } else if (optionsProp !== undefined && formatProp === undefined) { score -= removalPenalty; } else if (prop === "timeZoneName") { if (optionsProp === "short" || optionsProp === "shortGeneric") { if (formatProp === "shortOffset") { score -= offsetPenalty; } else if (formatProp === "longOffset") { score -= offsetPenalty + shortMorePenalty; } else if (optionsProp === "short" && formatProp === "long") { score -= shortMorePenalty; } else if (optionsProp === "shortGeneric" && formatProp === "longGeneric") { score -= shortMorePenalty; } else if (optionsProp !== formatProp) { score -= removalPenalty; } } else if (optionsProp === "shortOffset" && formatProp === "longOffset") { score -= shortMorePenalty; } else if (optionsProp === "long" || optionsProp === "longGeneric") { if (formatProp === "longOffset") { score -= offsetPenalty; } else if (formatProp === "shortOffset") { score -= offsetPenalty + longLessPenalty; } else if (optionsProp === "long" && formatProp === "short") { score -= longLessPenalty; } else if (optionsProp === "longGeneric" && formatProp === "shortGeneric") { score -= longLessPenalty; } else if (optionsProp !== formatProp) { score -= removalPenalty; } } else if (optionsProp === "longOffset" && formatProp === "shortOffset") { score -= longLessPenalty; } else if (optionsProp !== formatProp) { score -= removalPenalty; } } else if (optionsProp !== formatProp) { let values; if (prop === "fractionalSecondDigits") { values = [ 1, 2, 3 ]; } else { values = [ "2-digit", "numeric", "narrow", "short", "long" ]; } const optionsPropIndex = values.indexOf(optionsProp); const formatPropIndex = values.indexOf(formatProp); const delta = Math.max(-2, Math.min(formatPropIndex - optionsPropIndex, 2)); if (delta === 2) { score -= longMorePenalty; } else if (delta === 1) { score -= shortMorePenalty; } else if (delta === -1) { score -= shortLessPenalty; } else if (delta === -2) { score -= longLessPenalty; } } } if (score > bestScore) { bestScore = score; bestFormat = format; } } return { ...bestFormat }; }