Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 | 1x 1x 1x 1x 1x 32x 1x 52x 27x 27x 3x 23x 23x 23x 23x 2x 21x 168x 168x 126x 42x 42x 42x 168x 168x 168x 38x 21x 21x 11x 21x 3x 21x | import { DurationInput } from './types';
import { isZero } from './isZero';
import { getUnitCount } from './lib/getUnitCount';
import { UNITS_META, UNITS_META_MAP } from './lib/units';
import { checkAllUnitsNegative } from './lib/checkAllUnitsNegative';
interface ToStringOptions {
decimalDelimiter: string;
}
const joinComponents = (component: string[], delimiter: ToStringOptions['decimalDelimiter']) =>
component
.join('')
.replace(/\./g, delimiter);
/**
* Stringify a duration into an ISO duration string.
*
* @example
* toString({ years: 1, hours: 6 }) // 'P1YT6H'
* toString(6000) // 'PT6S'
*/
export const toString = (
duration: DurationInput,
options: Partial<ToStringOptions> = {},
): string => {
const finalOptions: ToStringOptions = {
// Commas are mentioned in the spec as the preferred decimal delimiter
decimalDelimiter: ',',
...options,
};
// Zero values are a special case, since "P" is not a valid value.
// At least one unit must be specified.
if (isZero(duration)) {
return 'P0D';
}
const {
maybeAbsDuration: parsed,
isAllNegative,
} = checkAllUnitsNegative(duration);
// Weeks should not be included in the output, unless it is the only unit.
if (getUnitCount(parsed) === 1 && parsed.weeks !== 0) {
return `P${parsed.weeks}W`;
}
const components = {
period: [] as string[],
time: [] as string[],
};
// Some units should be converted before stringifying.
// For example, weeks should not be mixed with other units, and milliseconds
// don't exist on ISO duration strings.
UNITS_META.forEach(({ unit: fromUnit, stringifyConvertTo: toUnit }) => {
if (toUnit == null) {
return;
}
const millisecondValue = parsed[fromUnit] * UNITS_META_MAP[fromUnit].milliseconds;
parsed[toUnit] += millisecondValue / UNITS_META_MAP[toUnit].milliseconds;
parsed[fromUnit] = 0;
});
// Push each non-zero unit to its relevant array
UNITS_META.forEach(({ unit, ISOPrecision, ISOCharacter }) => {
const value = parsed[unit];
if (ISOPrecision != null && value !== 0) {
components[ISOPrecision].push(`${value}${ISOCharacter}`);
}
});
// Build output string
let output = `P${joinComponents(components.period, finalOptions.decimalDelimiter)}`;
if (components.time.length) {
output += `T${joinComponents(components.time, finalOptions.decimalDelimiter)}`;
}
// Avoid "P-1DT-1H". Instead, output "-P1DT1H".
// https://github.com/dlevs/duration-fns/issues/22
if (isAllNegative) {
output = `-${output}`;
}
return output;
};
|