数字格式化的 js 库
Numeral.js,是一个用于格式化数字和处理数字的 js 库。
Tip:目前 Star 有 9.2k,5年以前就没有在更新。其文档写得不很清晰,比如它提供了多语言,但如何切换成中文,怎么使用却没有说,对于某些问题(abbreviations 报错)笔者只有从源码、更新日志和 Issues 中寻找答案。
使用它
node 中通过 npm 安装即可:
PS E:react-project> npm i numeral
Tip:也可以在浏览器中直接通过 src 的方式使用。
创建实例
通过 numeral() 创建一个实例:
var myNumeral = numeral(1000); var value = myNumeral.value(); // value 1000 console.log('value', value)
感觉好鸡肋,但可以取消格式化。比如将 1,000 处理成 1000:
var myNumeral2 = numeral('1,000'); var value2 = myNumeral2.value(); // value2 1000 console.log('value2', value2)
格式化
这部分是我们最关心的。比如笔者的需求有:
- 将后台的字节数根据数值大小自动转为
KB、MB、GB等对应的单位 - 数字太长,显示区域有限,比如将
123456789转为123.5m或123.5百万
format()
通过 format() 可以将 1000 格式化成 1,000,将 123456789 格式化成 123,456,789。请看示例:
var number = numeral(1000).format('0,0'); // number: 1,000 console.log('number: ', number); var number2 = numeral(123456789).format('0,0'); // number2: 123,456,789 console.log('number2: ', number2); // 四舍五入 var number3 = numeral(1.93).format('0,0'); // number3: 2 console.log('number3: ', number3); // 四舍五入 var number4 = numeral(1.23).format('0,0'); // number4: 1 console.log('number4: ', number4);
Tip:上面我们用了 0,0 这种格式,其他格式请直接看 numeral.js:
// node_modulesnumeraltestsnumeral.js describe('Format', function() { it('should format to a number', function() { var tests = [ [0, null, '0'], [0, '0.00', '0.00'], [null, null, '0'], [NaN, '0.0', '0.0'], [1.23,'0,0','1'], [10000,'0,0.0000','10,000.0000'], [10000.23,'0,0','10,000'], [-10000,'0,0.0','-10,000.0'], [10000.1234,'0.000','10000.123'], [10000,'0[.]00','10000'], [10000.1,'0[.]00','10000.10'], [10000.123,'0[.]00','10000.12'], [10000.456,'0[.]00','10000.46'], [10000.001,'0[.]00','10000'], [10000.45,'0[.]00[0]','10000.45'], [10000.456,'0[.]00[0]','10000.456'], [10000,'(0,0.0000)','10,000.0000'], [-10000,'(0,0.0000)','(10,000.0000)'], [-12300,'+0,0.0000','-12,300.0000'], [1230,'+0,0','+1,230'], [1230,'-0,0','1,230'], [-1230,'-0,0','-1,230'], [-1230.4,'0,0.0+','1,230.4-'], [-1230.4,'0,0.0-','1,230.4-'], [1230.4,'0,0.0-','1,230.4'], [100.78, '0', '101'], [100.28, '0', '100'], [1.932,'0.0','1.9'], [1.9687,'0','2'], [1.9687,'0.0','2.0'], [-0.23,'.00','-.23'], [-0.23,'(.00)','(.23)'], [0.23,'0.00000','0.23000'], [0.67,'0.0[0000]','0.67'], [3162.63,'0.0[00000000000000]','3162.63'], [1.99,'0.[0]','2'], [1.0501,'0.00[0]','1.05'], [1.005,'0.00','1.01'], // leading zero [0, '00.0', '00.0'], [0.23, '000.[00]', '000.23'], [4, '000', '004'], [10, '00000', '00010'], [1000, '000,0', '1,000'], [1000, '00000,0', '01,000'], [1000, '0000000,0', '0,001,000'], // abbreviations [2000000000,'0.0a','2.0b'], [1230974,'0.0a','1.2m'], [1460,'0a','1k'], [-104000,'0 a','-104 k'], [999950,'0.0a','1.0m'], [999999999,'0a','1b'], // forced abbreviations [-5444333222111, '0,0 ak', '-5,444,333,222 k'], [5444333222111, '0,0 am', '5,444,333 m'], [-5444333222111, '0,0 ab', '-5,444 b'], [-5444333222111, '0,0 at', '-5 t'], [123456, '0.0[0] ak', '123.46 k'], [150,'0.0 ak','0.2 k'] ], i, n, output; for (i = 0; i < tests.length; i++) { n = numeral(tests[i][0]); output = n.format(tests[i][1]); expect(output).to.equal(tests[i][2]); expect(typeof output).to.equal('string'); } }); });
字节转换
比如将 1024 转为 1KB,将 1024*1024 转为 1MB。将请看示例:
PS D:spug-study> node Welcome to Node.js v16.14.2. Type ".help" for more information. > let numeral = require('numeral') undefined > numeral(1024).format('0b') '1KB' > numeral(1024*1024).format('0b') '1MB' > numeral(1024*1024*1024).format('0b') '1GB' > numeral(1024*1024*1024*1024).format('0b') '1TB' > numeral(1024*1024*1024*1024*32).format('0b') '35TB' >
Tip:笔者直接在 node 环境下运行。更多格式化语法请看 bytes.js 文件。
// node_modulesnumeraltestsformatsbytes.js it('should format to bytes', function() { var decimal = 1000; var binary = 1024; var tests = [ [0,'0b','0B'], [null,'0 b','0 B'], [100,'0b','100B'], [binary * 2,'0 ib','2 KiB'], [Math.pow(binary, 2) * 5,'0ib','5MiB'], [Math.pow(binary, 3) * 7.343,'0.[0] ib','7.3 GiB'], [Math.pow(binary, 4) * 3.1536544,'0.000ib','3.154TiB'], [Math.pow(binary, 5) * 2.953454534534,'0ib','3PiB'], [decimal * 2,'0 b','2 KB'], [Math.pow(decimal, 2) * 5,'0b','5MB'], [Math.pow(decimal, 3) * 7.343,'0.[0] b','7.3 GB'], [Math.pow(decimal, 4) * 3.1536544,'0.000b','3.154TB'], [Math.pow(decimal, 5) * 2.953454534534,'0b','3PB'] ], i; for (i = 0; i < tests.length; i++) { expect(numeral(tests[i][0]).format(tests[i][1])).to.equal(tests[i][2]); } });
字节转数字
比如可以将 1KB 转为数字,但结果只是 1000,如果要 1024,需要使用 1 KiB。请看示例:
> numeral('1KB').value() 1000 > numeral('1 KiB').value() 1024 > numeral('1MB').value() 1000000
Tip:有关字节反解析的更多介绍请看 bytes.js。
// node_modulesnumeraltestsformatsbytes.js it('should unformat to number', function() { var decimal = 1000; var binary = 1024; var tests = [ ['0B', 0], ['0 B', 0], ['100B', 100], ['2 KiB', binary * 2], ['5MiB', Math.pow(binary, 2) * 5], ['7.3 GiB', Math.pow(binary, 3) * 7.3], ['3.154TiB', Math.pow(binary, 4) * 3.154], ['3PiB', Math.pow(binary, 5) * 3], ['2 KB', decimal * 2], ['5MB', Math.pow(decimal, 2) * 5], ['7.3 GB', Math.pow(decimal, 3) * 7.3], ['3.154TB', Math.pow(decimal, 4) * 3.154], ['3PB', Math.pow(decimal, 5) * 3] ], i; for (i = 0; i < tests.length; i++) { expect(numeral(tests[i][0]).value()).to.equal(tests[i][1]); } });
时间转换转化
将数字(秒)转为时间形式。请看示例:
> numeral(1).format('00:00:00') '0:00:01' > numeral(60).format('00:00:00') '0:01:00' > numeral(60*60).format('00:00:00') '1:00:00'
百分比转化
请看示例:
> numeral(0.974878234).format('0.000%') '97.488%' > numeral(0).format('0%') '0%' > numeral(1).format('0%') '100%'
Tip:更多介绍请看 node_modulesnumeraltestsformatspercentage.js。
货币转化
请看示例:
> numeral(1000.234).format('$0,0.00') '$1,000.23'
Tip:更多用法请看 currency.js。
// node_modulesnumeraltestsformatscurrency.js describe('Currency', function() { after(function() { numeral.reset(); }); it('should format to currency', function() { var tests = [ [0,'$0.00','$0.00'], [null,'$0.00','$0.00'], [0.99,'$0,0.00','$0.99'], [1000.234,'$0,0.00','$1,000.23'], [1001,'$ 0,0.[00]','$ 1,001'], [1000.234,'0,0.00 $','1,000.23 $'], [-1000.234,'0,0.00 $','-1,000.23 $'], [-1000.234,'($0,0)','($1,000)'], [-1000.234,'(0,0$)','(1,000$)'], [-1000.234,'(0,0 $)','(1,000 $)'], [-1000.234,'$0.00','-$1000.23'], [-1000.234,'$ 0.00','-$ 1000.23'], [1230974,'($0.00 a)','$1.23 m'], [-1000.234,'$ (0,0)','$ (1,000)'], [-1000.234,'$(0,0)','$(1,000)'], [-1000.234,'$ (0,0.00)','$ (1,000.23)'], [-1000.234,'$(0,0.00)','$(1,000.23)'], [-1000.238,'$(0,0.00)','$(1,000.24)'], [-1000.234,'$-0,0','$-1,000'], [-1000.234,'$ -0,0','$ -1,000'], [1000.234,'$ (0,0)','$ 1,000'], [1000.234,'$(0,0)','$1,000'], [1000.234,'$ (0,0.00)','$ 1,000.23'], [1000.234,'$(0,0.00)','$1,000.23'], [1000.238,'$(0,0.00)','$1,000.24'], [1000.234,'$-0,0','$1,000'], [1000.234,'$ -0,0','$ 1,000'] ], i; for (i = 0; i < tests.length; i++) { expect(numeral(tests[i][0]).format(tests[i][1])).to.equal(tests[i][2]); } }); it('should unformat to currency', function() { var tests = [ ['$0.00', 0], ['$0.99', 0.99], ['$1,000.23', 1000.23], ['1,000.23 $', 1000.23], ['($1,000)', -1000], ['-1,000$', -1000], ['$1.23 m', 1230000], ], i; for (i = 0; i < tests.length; i++) { expect(numeral(tests[i][0]).value()).to.equal(tests[i][1]); } }); });
指数转化
请看示例:
> numeral(77777777.1234).format('0.0e+0') '7.8e+7'
Tip:更多用法请看 exponential.js。
// node_modulesnumeraltestsformatsexponential.js it('should format to exponential notation', function() { var tests = [ [0,'0e+0','0e+0'], [null,'0e+0','0e+0'], [1,'0e+0','1e+0'], [77.1234,'0.0e+0','7.7e+1'], [0.000000771234,'0.0e-0','7.7e-7'], [-0.000000771234,'0.00e-0','-7.71e-7'], [77.1234,'0.000e+0','7.712e+1'], [-1000830298,'0.0[000]e+0','-1.0008e+9'] ], i; for (i = 0; i < tests.length; i++) { expect(numeral(tests[i][0]).format(tests[i][1])).to.equal(tests[i][2]); } });
比特率转化
比特率,是指单位时间内传送的比特(bit)数,单位为bps(bit per second)。
> numeral(.0056).format('0 BPS') '56 BPS'
Tip:更多用法请看 bps.js:
// node_modulesnumeraltestsformatsbps.js it('should format to bps', function() { var tests = [ [0,'0 BPS','0 BPS'], [0.0001, '0 BPS', '1 BPS'], [.0056, '0 BPS', '56 BPS'], [.25, '0BPS', '2500BPS'], [.000001, '0.00 BPS', '0.01 BPS'] ], i; for (i = 0; i < tests.length; i++) { expect(numeral(tests[i][0]).format(tests[i][1])).to.equal(tests[i][2]); } });
四则运算
numeral 提供加减乘除四则运算的方法,例如 1000 加 10 等于 1010。请看示例:
> numeral(1000).add(10).value() 1010
Tip:更多介绍请看 numeral.js。
// node_modulesnumeraltestsnumeral.js describe('Manipulate', function() { // 加法 describe('Add', function() { it('should add', function() { var tests = [ [1000,10,1010], [0.5,3,3.5], [-100,200,100], [0.1,0.2,0.3], [0.28,0.01,0.29], [0.289999,0.000001,0.29], [0.29,0.01,0.3] ], num; for (var i = 0; i < tests.length; i++) { num = numeral(tests[i][0]); num.add(tests[i][1]); expect(num.value()).to.equal(tests[i][2]); } }); }); // 减法 describe('Subtract', function() { it('should subtract', function() { var tests = [ [1000,10,990], [0.5,3,-2.5], [-100,200,-300], [0.3,0.1,0.2], [0.28,0.01,0.27], [0.29,0.01,0.28] ], num; for (var i = 0; i < tests.length; i++) { num = numeral(tests[i][0]); num.subtract(tests[i][1]); expect(num.value()).to.equal(tests[i][2]); } }); }); // 乘法 describe('Multiply', function() { it('should multiply', function() { var tests = [ [1000,10,10000], [0.5,3,1.5], [-100,200,-20000], [0.1,0.2,0.02], [0.28,0.01,0.0028], [0.29,0.01,0.0029], [0.00000231,10000000,23.1] ], num; for (var i = 0; i < tests.length; i++) { num = numeral(tests[i][0]); num.multiply(tests[i][1]); expect(num.value()).to.equal(tests[i][2]); } }); }); // 除法 describe('Divide', function() { it('should divide', function() { var tests = [ [1000,10,100], [0.5,3,0.16666666666666666], [-100,200,-0.5], [5.3,0.1,53], [0.28,0.01,28], [0.29,0.01,29] ], num; for (var i = 0; i < tests.length; i++) { num = numeral(tests[i][0]); num.divide(tests[i][1]); expect(num.value()).to.equal(tests[i][2]); } }); }); // 差值。例如 1000 和 10 相差 990。 describe('Difference', function() { it('should find a difference', function() { var tests = [ [1000,10,990], [0.5,3,2.5], [-100,200,300], [0.3,0.2,0.1], [0.28,0.01,0.27], [0.29,0.01,0.28] ], num; for (var i = 0; i < tests.length; i++) { num = numeral(tests[i][0]); expect(num.difference(tests[i][1])).to.equal(tests[i][2]); } }); }); // 四舍五入。 describe('Rounding', function() { it('should format with rounding', function() { var tests = [ // value, format string, expected w/ floor, expected w/ ceil [2280002, '0.00a', '2.28m', '2.29m'], [10000.23,'0,0','10,000', '10,001'], [1000.234,'0,0.00','1,000.23', '1,000.24'], [0.97487823,'0.000','0.974','0.975'], [-0.433,'0.0','-0.5', '-0.4'] ], i; for (i = 0; i < tests.length; i++) { // floor expect(numeral(tests[i][0]).format(tests[i][1], Math.floor)).to.equal(tests[i][2]); // ceil expect(numeral(tests[i][0]).format(tests[i][1], Math.ceil)).to.equal(tests[i][3]); } }); }); });
多语言
需求:数字很长时,由于排版的考虑,需要将数字显示的更短,转为指数勉强可以,但对很多人还是不友好,如果能转为 123.5百万 这种形式就完美了。
numeral 提供了缩写,比如可以将 1230974 转为 1.2m(m,指百万):
// node_modulesnumeraltestsnumeral.js ... // abbreviations [2000000000,'0.0a','2.0b'], [1230974,'0.0a','1.2m'], [1460,'0a','1k'], [-104000,'0 a','-104 k'], [999950,'0.0a','1.0m'], [999999999,'0a','1b'],
请看示例:
const numeral = require('numeral'); var number5 = numeral(123456789).format('0.0a') // 123.5m console.log('number5: ', number5);
123.5m 是多少,能否转为中文?笔者在 chs.js 中找到如下代码:
// node_modulesnumerallocaleschs.js numeral.register('locale', 'chs', { delimiters: { thousands: ',', decimal: '.' }, abbreviations: { thousand: '千', million: '百万', billion: '十亿', trillion: '兆' }, ordinal: function (number) { return '.'; }, currency: { symbol: '¥' } });
通过引入 chs 并切换成中文,成功将 123456789 转为 123.5百万。请看示例:
const numeral = require('numeral'); // 加载中文 + require('numeral/locales/chs') // 切换成中文 + numeral.locale('chs') const number5 = numeral(123456789).format('0.0a') // number5: 123.5百万 console.log('number5: ', number5);
Tip:对于单页面项目,在其他组件中若需要使用英文,比如不要 123.5百万,而要 123.5m,直接切换语言(numeral.locale('en'))即可。就像这样:
... const number5 = numeral(123456789).format('0.0a') // number5: 123.5百万 console.log('number5: ', number5); + numeral.locale('en') const number6 = numeral(123456789).format('0.0a') // number6: 123.5m console.log('number6: ', number6);
笔者的示例
import React from 'react'; const numeral = require('numeral'); require('numeral/locales/chs') numeral.locale('chs') function Test() { const number = numeral(1000).format('0,0'); // number: 1,000 console.log('number: ', number); const number2 = numeral(123456789).format('0,0'); // number2: 123,456,789 console.log('number2: ', number2); // 四舍五入 const number3 = numeral(1.93).format('0,0'); // number3: 2 console.log('number3: ', number3); // 四舍五入 const number4 = numeral(1.23).format('0,0'); // number4: 1 console.log('number4: ', number4); const number5 = numeral(123456789).format('0.0a') // number5: 123.5百万 console.log('number5: ', number5); numeral.locale('en') const number6 = numeral(123456789).format('0.0a') // number6: 123.5m console.log('number6: ', number6); return ( <div> react 项目 </div> ) } export default Test