number-reads-cn
Version:
数字中文读法转换工具(电话读法、数值读法、序列读法、金额读法、大写读法)
185 lines (184 loc) • 5.73 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.chineseReadToNumber = exports.chineseToNumber = exports.getAllNumberReads = void 0;
const digitToChineseMap = {
'0': '零',
'1': '一',
'2': '二',
'3': '三',
'4': '四',
'5': '五',
'6': '六',
'7': '七',
'8': '八',
'9': '九',
};
const digitToPhoneMap = {
'0': '零',
'1': '夭',
'2': '二',
'3': '三',
'4': '四',
'5': '五',
'6': '六',
'7': '七',
'8': '八',
'9': '九',
};
const digitToUppercaseMap = {
'0': '零',
'1': '壹',
'2': '贰',
'3': '叁',
'4': '肆',
'5': '伍',
'6': '陆',
'7': '柒',
'8': '捌',
'9': '玖',
};
/**
* 数值中文大写(金额式读法)—— 支持亿以内
*/
const numberToChineseValue = (numStr) => {
const num = Number(numStr);
if (isNaN(num))
return numStr;
const digitToChinese = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九'];
const unit = ['', '十', '百', '千'];
const sectionUnit = ['', '万', '亿', '兆'];
const toSection = (sectionNum) => {
let str = '';
let zero = true;
const sectionArr = sectionNum.split('').reverse();
for (let i = 0; i < sectionArr.length; i++) {
const n = parseInt(sectionArr[i]);
if (n === 0) {
if (!zero) {
zero = true;
str = digitToChinese[0] + str;
}
}
else {
zero = false;
str = digitToChinese[n] + unit[i] + str;
}
}
return str.replace(/零+$/g, '');
};
const numArr = numStr.split('').reverse().join('').match(/.{1,4}/g) || [];
let result = '';
for (let i = 0; i < numArr.length; i++) {
const section = toSection(numArr[i].split('').reverse().join(''));
if (section !== '') {
result = section + sectionUnit[i] + result;
}
else {
if (!result.startsWith('零'))
result = '零' + result;
}
}
result = result.replace(/^一十/, '十');
result = result.replace(/零+/g, '零');
result = result.replace(/零+$/g, '');
return result;
};
/**
* 获取所有中文数字读法
*/
const getAllNumberReads = (input) => {
const phoneRead = input
.split('')
.map(char => digitToPhoneMap[char] || char);
const phoneSegments = [
phoneRead.slice(0, 3).join(''),
phoneRead.slice(3, 7).join(''),
phoneRead.slice(7).join(''),
];
const telephone = phoneSegments.filter(s => s).join(' ');
const number = numberToChineseValue(input);
const currency = number + '元';
const sequence = input
.split('')
.map(char => digitToChineseMap[char] || char)
.join(' ');
const upper = input
.split('')
.map(char => digitToUppercaseMap[char] || char)
.join('');
return [
{ label: '电话读法', value: telephone },
{ label: '数值读法', value: number },
{ label: '金额读法', value: currency },
{ label: '序列读法', value: sequence },
{ label: '大写读法', value: upper },
];
};
exports.getAllNumberReads = getAllNumberReads;
/**
* 将中文数字读法(如:一百八十六)反向转为数字(如:186)
* 暂只支持简体数字读法,不支持金额/大写/序列等
*/
const chineseToNumber = (chinese) => {
const charToDigit = {
'零': 0, '一': 1, '二': 2, '三': 3, '四': 4,
'五': 5, '六': 6, '七': 7, '八': 8, '九': 9
};
const unitMap = {
'十': 10,
'百': 100,
'千': 1000,
'万': 10000,
'亿': 100000000
};
let result = 0;
let section = 0;
let number = 0;
let unit = 1;
for (let i = chinese.length - 1; i >= 0; i--) {
const char = chinese[i];
if (char in charToDigit) {
number = charToDigit[char];
if (unit > 1) {
section += number * unit;
unit = 1;
}
else {
section += number;
}
}
else if (char in unitMap) {
unit = unitMap[char];
if (unit >= 10000) {
result += section * unit;
section = 0;
}
}
else {
// 忽略非数字字符
}
}
result += section;
return isNaN(result) ? null : result;
};
exports.chineseToNumber = chineseToNumber;
/**
* 支持 getAllNumberReads 返回的所有读法反向转为数字
*/
const chineseReadToNumber = (read) => {
// 去除空格和单位
const cleanRead = read.replace(/[元\s]/g, '');
// 如果是序列或电话读法(逐个数字中文)
if (/^[零一二三四五六七八九夭]+$/.test(cleanRead)) {
const map = { '夭': '1', '零': '0', '一': '1', '二': '2', '三': '3', '四': '4', '五': '5', '六': '6', '七': '7', '八': '8', '九': '9' };
return Number(cleanRead.split('').map(c => map[c] || '').join('')) || null;
}
// 如果是大写读法(壹贰叁)
if (/^[壹贰叁肆伍陆柒捌玖零]+$/.test(cleanRead)) {
const map = { '壹': '1', '贰': '2', '叁': '3', '肆': '4', '伍': '5', '陆': '6', '柒': '7', '捌': '8', '玖': '9', '零': '0' };
return Number(cleanRead.split('').map(c => map[c] || '').join('')) || null;
}
// 否则用中文数值解析(如 一百八十六)
return (0, exports.chineseToNumber)(cleanRead);
};
exports.chineseReadToNumber = chineseReadToNumber;