ohayolibs
Version:
Ohayo is a set of essential modules for ohayojp.
82 lines (78 loc) • 3.15 kB
text/typescript
import { NzSafeAny } from 'ng-zorro-antd/core/types';
import { NumberToChineseOptions } from './number-to-chinese.interfaces';
export function numberToChinese(value: number | string, rmb: boolean = true, options?: NumberToChineseOptions): string {
options = {
minusSymbol: '负',
validThrow: false,
...options,
};
if (typeof value === 'number') value = value.toString();
if (!/^-?\d+(\.\d+)?$/.test(value) && options.validThrow) throw new Error(`${value} is invalid number type`);
let integer: number | string;
let decimal: number | string | null;
[integer, decimal] = value.split('.');
let symbol = '';
if (integer.startsWith('-')) {
symbol = options.minusSymbol!;
integer = integer.substr(1);
}
if (/^-?\d+$/.test(value)) decimal = null;
integer = (+integer).toString();
const unit = {
num: rmb
? ['', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖', '点']
: ['', '一', '二', '三', '四', '五', '六', '七', '八', '九', '点'],
radice: rmb
? ['', '拾', '佰', '仟', '万', '拾', '佰', '仟', '亿', '拾', '佰', '仟', '万亿', '拾', '佰', '仟', '兆', '拾', '佰', '仟']
: ['', '十', '百', '千', '万', '十', '百', '千', '亿', '十', '百', '千', '万亿', '十', '百', '千', '兆', '十', '百', '千'],
dec: ['角', '分', '厘', '毫'],
};
if (rmb) value = (+value).toFixed(5).toString();
let integerRes = '';
const integerCount = integer.length;
if (integer === '0' || integerCount === 0) {
integerRes = '零';
} else {
let cnDesc = '';
for (let i = 0; i < integerCount; i++) {
const n = +integer[i];
const j = integerCount - i - 1;
const isZero = i > 1 && n !== 0 && integer[i - 1] === '0';
const cnZero = isZero ? '零' : '';
const isEmpptyUnit = (n === 0 && j % 4 !== 0) || integer.substr(i - 3, 4) === '0000';
const descMark = cnDesc;
let cnNum = unit.num[n];
cnDesc = isEmpptyUnit ? '' : unit.radice[j];
// 第一位是一十
if (i === 0 && cnNum === '一' && cnDesc === '十') cnNum = '';
const isChangeEr =
n > 1 &&
cnNum === '二' && // 去除首位
['', '十', '百'].indexOf(cnDesc) === -1 && // 不读两\两十\两百
descMark !== '十'; // 不读十两
if (isChangeEr) cnNum = '两';
integerRes += cnZero + cnNum + cnDesc;
}
}
// 小数部分拼接
let decimalRes = '';
const decimalCount = decimal ? decimal.toString().length : 0;
if (decimal === null) {
decimalRes = rmb ? '整' : '';
} else if (decimal === '0') {
decimalRes = '零';
} else {
for (let i = 0; i < decimalCount; i++) {
if (rmb && i > unit.dec.length - 1) break;
const n = decimal[i];
const cnZero = n === '0' ? '零' : '';
const cnNum = (unit.num as NzSafeAny)[n];
const cnDesc = rmb ? unit.dec[i] : '';
decimalRes += cnZero + cnNum + cnDesc;
}
}
const ret =
symbol +
(rmb ? integerRes + (decimalRes === '零' ? '元整' : `元${decimalRes}`) : integerRes + (decimalRes === '' ? '' : `点${decimalRes}`));
return ret;
}