interface INumberConversionItem<K> {
    unit: K; // 单位
    carry: number; // 进制
}
 
interface INumberConversionOpts<K> {
    items: INumberConversionItem<K>[];
    parseFunc: (data: INumberConversionItem<K> & { index: number; value: number }) => string;
    minUnit?: K; // 最小单位
}
 
function createNumberConversion<K>(opts: INumberConversionOpts<K>) {
    const { items, parseFunc, minUnit } = opts;
    return (data: number) => {
        let index = 0;
        let value = data;
        while (index < items.length - 1 && value >= items[index].carry) {
            value /= items[index].carry;
            index++;
        }
        const minIndex = minUnit ? items.findIndex(item => item.unit === minUnit) : -1;
        if (minIndex !== -1) {
            while (index < minIndex) {
                value /= items[index].carry;
                index++;
            }
        }
 
        return parseFunc({ ...items[index], index, value });
    };
}
 
// ----------------------------
 
const sizeUnits = ['B', 'K', 'M', 'G', 'T'] as const;
const formatSizeNumber = createNumberConversion({
    items: sizeUnits.map(unit => ({ unit, carry: 1024 })),
    parseFunc: ({ unit, value }) => `${value.toFixed(0)}${unit}`,
});
 
[
    '1',
    '1024',
    '1024 * 1024',
    '1024 * 1024 * 1024',
    '1024 * 1024 * 1024 * 1024',
    '1024 * 1024 * 1024 * 1024 * 99999',
].forEach(item => {
    console.log(`${formatSizeNumber(eval(item))}: ${item}`);
});
 
// 1B: 1
// 1K: 1024
// 1M: 1024 * 1024
// 1G: 1024 * 1024 * 1024
// 1T: 1024 * 1024 * 1024 * 1024
// 99999T: 1024 * 1024 * 1024 * 1024 * 99999
 
// ----------------------------
 
const formatTimeNumber = createNumberConversion({
    items: [
        { unit: '秒', carry: 60 },
        { unit: '分钟', carry: 60 },
        { unit: '小时', carry: 24 },
        { unit: '天', carry: 30 },
        { unit: '个月', carry: 12 },
        { unit: '年', carry: Infinity },
    ] as const,
    parseFunc: ({ unit, value }) => `${value.toFixed(0)}${unit}`,
});
 
[
    '1',
    '60',
    '60 * 60',
    '60 * 60 * 24',
    '60 * 60 * 24 * 30',
    '60 * 60 * 24 * 30 * 12',
    '60 * 60 * 24 * 30 * 12 * 1000',
].forEach(item => {
    console.log(`${formatTimeNumber(eval(item))}: ${item}`);
});
 
// 1秒: 1
// 1分钟: 60
// 1小时: 60 * 60
// 1天: 60 * 60 * 24
// 1个月: 60 * 60 * 24 * 30
// 1年: 60 * 60 * 24 * 30 * 12
// 1000年: 60 * 60 * 24 * 30 * 12 * 1000