编辑代码

// 辅助函数:检查是否是标准格式
function isStandardFormat(varValue) {
    const patterns = [
        /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/,
        /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}$/,
        /^\d{4}-\d{2}-\d{2}$/,
        /^\d{2}:\d{2}:\d{2}$/
    ];
    return patterns.some(pattern => pattern.test(varValue));
}

// 辅助函数:解析varValue为Date对象,并验证有效性
function parseVarValue(varValue) {
    if (/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/.test(varValue)) {
        return parseDateTime(varValue);
    } else if (/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}$/.test(varValue)) {
        return parseDateTimeHM(varValue);
    } else if (/^\d{4}-\d{2}-\d{2}$/.test(varValue)) {
        return parseDate(varValue);
    } else if (/^\d{2}:\d{2}:\d{2}$/.test(varValue)) {
        return parseTime(varValue);
    }
    return null;
}

function parseDateTime(varValue) {
    const [datePart, timePart] = varValue.split(' ');
    const date = parseDatePart(datePart);
    if (!date) return null;
    const time = parseTimePart(timePart, true);
    if (!time) return null;
    date.setHours(time.hours, time.minutes, time.seconds);
    return date;
}

function parseDateTimeHM(varValue) {
    const [datePart, timePart] = varValue.split(' ');
    const date = parseDatePart(datePart);
    if (!date) return null;
    const time = parseTimePart(timePart, false);
    if (!time) return null;
    date.setHours(time.hours, time.minutes, 0);
    return date;
}

function parseDatePart(datePart) {
    const [yearStr, monthStr, dayStr] = datePart.split('-');
    const year = parseInt(yearStr, 10);
    const month = parseInt(monthStr, 10) - 1;
    const day = parseInt(dayStr, 10);
    if (month < 0 || month > 11) return null;
    const date = new Date(year, month, day);
    if (date.getFullYear() !== year || date.getMonth() !== month || date.getDate() !== day) {
        return null;
    }
    return date;
}

function parseTimePart(timePart, includeSeconds) {
    const parts = timePart.split(':');
    if (includeSeconds && parts.length !== 3) return null;
    if (!includeSeconds && parts.length !== 2) return null;
    const hours = parseInt(parts[0], 10);
    const minutes = parseInt(parts[1], 10);
    const seconds = includeSeconds ? parseInt(parts[2], 10) : 0;
    if (hours < 0 || hours >= 24) return null;
    if (minutes < 0 || minutes >= 60) return null;
    if (includeSeconds && (seconds < 0 || seconds >= 60)) return null;
    return { hours, minutes, seconds };
}

function parseDate(varValue) {
    const date = parseDatePart(varValue);
    if (!date) return null;
    date.setHours(0, 0, 0);
    return date;
}

function parseTime(varValue) {
    const time = parseTimePart(varValue, true);
    if (!time) return null;
    const now = new Date();
    const date = new Date(now.getFullYear(), now.getMonth(), now.getDate(), time.hours, time.minutes, time.seconds);
    return date;
}

// 辅助函数:格式化Date对象
function formatDate(date, formatString) {
    const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
    const pad = (n) => n.toString().padStart(2, '0');
    const year = date.getFullYear();
    const month = date.getMonth();
    const day = date.getDate();
    const hours = date.getHours();
    const minutes = date.getMinutes();
    const seconds = date.getSeconds();
    const monthStr = months[month];
    const replacements = {
        'yyyy': year,
        'MMM': monthStr,
        'MM': pad(month + 1),
        'dd': pad(day),
        'HH': pad(hours),
        'mm': pad(minutes),
        'ss': pad(seconds)
    };
    let result = formatString;
    // 替换顺序需要考虑长的部分先替换
    result = result.replace(/yyyy/g, replacements['yyyy']);
    result = result.replace(/MMM/g, replacements['MMM']);
    result = result.replace(/MM/g, replacements['MM']);
    result = result.replace(/dd/g, replacements['dd']);
    result = result.replace(/HH/g, replacements['HH']);
    result = result.replace(/mm/g, replacements['mm']);
    result = result.replace(/ss/g, replacements['ss']);
    return result;
}

function format(varValue, formatString) {
    if (typeof varValue === 'undefined' || varValue === null) {
        return ''; // 如果变量未定义或为null,则返回空字符串
    }

    // 检查是否为整数格式(仅包含数字)
    if (/^\d+$/.test(formatString)) {
    
        if (typeof varValue !== 'number' || isNaN(varValue)) {
            return null; 
        }
        var sign = varValue < 0 ? -1 : 1;
        varValue = Math.abs(varValue); 
        var integerPart = Math.trunc(varValue);
        var integerPartStr = integerPart.toString();
        var resultStr = integerPartStr.length <= formatString ? integerPartStr : integerPartStr.substring(0, formatString);
        var resultInt = parseInt(resultStr, 10) * sign;

        return isFinite(resultInt) ? resultInt : null; 
    }

    // 检查是否为小数格式(包含数字和一个小数点)
    if (/^\d+\.\d+$/.test(formatString)) {
         if (typeof varValue !== 'number' || isNaN(varValue)) {
            return null; 
        }
        // 解析格式字符串
        const [integerLengthStr, decimalPlacesStr] = formatString.split('.');
        const integerLength = parseInt(integerLengthStr, 10);
        const decimalPlaces = parseInt(decimalPlacesStr, 10);
    
        // 检查解析是否成功以及参数是否有效
        if (isNaN(integerLength) || isNaN(decimalPlaces) || integerLength <= 0 || decimalPlaces < 0) {
            return '';
        }
    
        // 将 var1 转换为字符串,并保留指定的小数位数
        let var1Str = varValue.toFixed(decimalPlaces);
    
        // 去除末尾不必要的零(但保留一个零以保持小数位数)
        var1Str = var1Str.replace(/(\.\d*[1-9])\d*0+|\.\d+0+$/g, '$1').replace(/\.$/, '');
    
        // 去掉可能的正负号
        let absoluteVar1Str = var1Str.replace(/^-/, '').replace(/^\+/, '');
    
        // 分割整数部分和小数部分
        let [integerPart, decimalPart] = absoluteVar1Str.split('.');
    
        // 根据需要保留的小数位数处理小数部分
        let formattedDecimalPart = '';
        if (decimalPart && decimalPlaces > 0) {
            formattedDecimalPart = decimalPart.slice(0, decimalPlaces);
            // 去除末尾不必要的零(但保留一个零以保持至少指定的小数位数,除非它是整数部分后的唯一零)
            formattedDecimalPart = formattedDecimalPart.replace(/\.?0+$/, '');
            if (formattedDecimalPart === '' && decimalPlaces > 0) {
                formattedDecimalPart = '0'; // 如果没有小数部分但指定了小数位数且不是整数,则至少保留一个零
            }
        }
    
        // 截取整数部分的前 integerLength 位
        let slicedIntegerPart = integerPart.slice(0, integerLength);
    
        // 构建最终的结果字符串
        let result = slicedIntegerPart;
        if (formattedDecimalPart) {
            result += '.' + formattedDecimalPart;
        }
    
        // 根据原数的符号添加正负号
        // 根据原数的符号添加正负号
        result = (varValue >= 0 ? '' : '-') + result;
    
        // 返回最终结果
        return result;
}

    // 检查是否为货币格式(以$开头,后面跟随数字和小数点)
    if (/^\$\d+(\.\d+)?$/.test(formatString)) {
        // 提取长度值,假设 formatString 总是以 '$' 开头,后面跟着数字
        const lengthMatch = formatString.match(/^\$(\d+)/);
        if (!lengthMatch) {
            throw new Error('Invalid format string. It should start with "$" followed by a number.');
        }
        const maxLength = parseInt(lengthMatch[1], 10);
    
        // 将 varValue 转换为字符串
        let valueStr = varValue.toString();
    
        // 如果 varValue 的长度小于等于指定的长度,直接返回
        if (valueStr.length <= maxLength) {
            return valueStr;
        }
    
        // 否则,截取指定长度的内容并返回
        return valueStr.slice(0, maxLength);
    }

    // 检查是否为日期格式
    // 预定义的日期时间格式列表
    const allowedFormats = [
        'yyyy-MM-dd',
        'dd-MMM-yyyy',
        'yyyy-MM-dd HH:mm',
        'yyyy-MM-dd HH:mm:ss',
        'dd-MMM-yyyy HH:mm',
        'dd-MMM-yyyy HH:mm:ss',
        'HH:mm:ss',
        'HH:mm',
        'yyyy-MM',
        'MMM-yyyy',
        'yyyy-MM-dd HH',
        'dd-MMM-yyyy HH',
        'HH'
    ];

    // 检查formatString是否允许
    if (!allowedFormats.includes(formatString)) {
        return null;
    }

    // 检查varValue是否是标准格式
    if (typeof varValue !== 'string' || !isStandardFormat(varValue)) {
        return null;
    }

    // 解析varValue为Date对象
    const date = parseVarValue(varValue);
    if (!date || isNaN(date.getTime())) {
        return null;
    }

// 格式化Date对象
    return formatDate(date, formatString);
}

// 示例用法:
console.log(format(21.2, 2)); // 输出: 21(整数)
console.log(format(-12345.67, 3)); // 输出: -123(整数)
console.log(format(123.456, 8)); // 输出: 123(整数,虽然指定长度为8,但整数部分只有3位)
console.log(format("abc", 5)); // 输出: null(因为"abc"不是数值类型)
console.log(format(12345678901234567890, 5)); // 输出:12345
console.log(format('2017-09-11', 'yyyy-dd'));    // 输出 "2017-09-11 00:00"