@financial-times/n-conversion-forms
Version:
Containing jsx components and styles for forms included on Accounts and Acquisition apps (next-signup, next-profile, next-retention, etc).
105 lines (87 loc) • 2.91 kB
JavaScript
/**
* Returns period converted to time if found
* otherwise returns empty string to avoid show information not mapped.
* @param {string} iso8601Value: PxY (yearly), PxM (montly), PxW (weekly), of PxD (daily), where x is the amount of years/months/weeks/days
* @param {boolean} excludeAmountWhenSingular: Omits the amount from the returned string when the discerned amount is singular.
* @returns {string}
*/
const getDurationFromISO8601Value = ({
iso8601Value,
excludeAmountWhenSingular = true,
}) => {
const amount = iso8601Value.substring(1, iso8601Value.length - 1);
const PERIOD_UNIT_CODE_TO_PLURAL_TERM_MAP = {
Y: 'years',
M: 'months',
W: 'weeks',
D: 'days',
};
const PERIOD_UNIT_CODE_TO_SINGULAR_TERM_MAP = {
Y: 'year',
M: 'month',
W: 'week',
D: 'day',
};
const periodUnitCode = iso8601Value.substring(iso8601Value.length - 1);
if (iso8601Value) {
const unit =
amount === '1'
? PERIOD_UNIT_CODE_TO_SINGULAR_TERM_MAP[periodUnitCode] || ''
: PERIOD_UNIT_CODE_TO_PLURAL_TERM_MAP[periodUnitCode] || '';
return amount === '1' && excludeAmountWhenSingular
? unit
: `${amount} ${unit}`;
}
return '';
};
const DAYS_IN_A_YEAR = 365; // Disregarding leap years
const DAYS_IN_A_MONTH = 30; // Approximate
const DAYS_IN_A_WEEK = 7;
const DAYS_IN_90_DAYS = 90;
const DAYS_IN_52_WEEKS = 52 * DAYS_IN_A_WEEK;
/**
* Parses an ISO 8601 duration string and converts it into an approximate total number of days.
* @param {string} iso8601Duration: PxY (yearly), PxM (monthly), PxW (weekly), or PxD (daily), where x is the amount.
* @returns {number|null} Total number of days represented by the duration or null if the input is not a valid ISO 8601 duration.
*/
const parseISODurationToDays = (iso8601Duration) => {
const match = iso8601Duration.match(
/^P(?:(\d+)Y)?(?:(\d+)M)?(?:(\d+)W)?(?:(\d+)D)?$/
);
if (!match) return null;
const years = Number(match[1] ?? 0);
const months = Number(match[2] ?? 0);
const weeks = Number(match[3] ?? 0);
const days = Number(match[4] ?? 0);
return (
years * DAYS_IN_A_YEAR +
months * DAYS_IN_A_MONTH +
weeks * DAYS_IN_A_WEEK +
days
);
};
/**
* Approximate check of whether an ISO 8601 duration is 52 weeks or shorter.
* @param {string} iso8601Duration
* @returns {boolean}
*/
const is52WeeksOrLonger = (iso8601Duration) => {
const totalDays = parseISODurationToDays(iso8601Duration);
if (totalDays === null) return false;
return totalDays >= DAYS_IN_52_WEEKS;
};
/**
* Approximate check of whether an ISO 8601 duration is 90 days or longer.
* @param {string} iso8601Duration
* @returns {boolean}
*/
const is90DaysOrLonger = (iso8601Duration) => {
const totalDays = parseISODurationToDays(iso8601Duration);
if (totalDays === null) return false;
return totalDays >= DAYS_IN_90_DAYS;
};
module.exports = {
getDurationFromISO8601Value,
is52WeeksOrLonger,
is90DaysOrLonger,
};