Skip to content

Commit ea3b5e7

Browse files
committed
Merge pull request airbnb#10 from drivetribe/approx-number
Adding number formatter package
2 parents a869e04 + 3508c8f commit ea3b5e7

File tree

9 files changed

+218
-0
lines changed

9 files changed

+218
-0
lines changed

utils/number-formatters/.babelrc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"presets": [
3+
"es2015",
4+
"react",
5+
"stage-2"
6+
]
7+
}

utils/number-formatters/.eslintrc

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
{
2+
"parser": "babel-eslint",
3+
"extends": "airbnb",
4+
"env": {
5+
"browser": true,
6+
"node": true,
7+
"mocha": true
8+
},
9+
"ecmaFeatures": {
10+
"forOf": true,
11+
"jsx": true,
12+
"es6": true,
13+
"experimentalObjectRestSpread": true,
14+
"modules": true
15+
},
16+
"rules": {
17+
"comma-dangle": 0,
18+
"max-len": [1, {"code": 120}],
19+
"indent": [2, 2, {"SwitchCase": 1}],
20+
"react/prop-types": 0,
21+
"global-require": 0,
22+
"prefer-template": 0
23+
},
24+
"plugins": [
25+
"flowtype",
26+
"jsx-a11y",
27+
"react"
28+
],
29+
"settings": {
30+
"flowtype": {
31+
"onlyFilesWithFlowAnnotation": false
32+
}
33+
}
34+
}

utils/number-formatters/.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
node_modules
2+
npm-debug.log
3+
lib

utils/number-formatters/.npmignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# folder to not push to npmjs
2+
src/
3+
node_modules/

utils/number-formatters/.travis.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# language: node_js
2+
#
3+
# node_js:
4+
# - 6.0.0
5+
#
6+
# install:
7+
# - npm install
8+
# script:
9+
# - npm run compile
10+
# after_success:
11+
# - npm run semantic-release

utils/number-formatters/README.md

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# @drivetribe/utils-number-formatters
2+
3+
Collection of number formatter functions to change numbers and dates for display purposes.
4+
5+
## Installation
6+
7+
Install the module directly from npm:
8+
9+
```
10+
npm install @drivetribe/utils-number-formatters --save
11+
```
12+
13+
## Formatters
14+
15+
### Approximate
16+
17+
Approximates large numbers, ie 6426 -> "6.4K".
18+
19+
`approximate(quant: number||string): string`
20+
21+
#### Example
22+
23+
```js
24+
import { approximate } from '@drivetribe/utils-number-formatters';
25+
26+
approximate(5134924); // "5.1M"
27+
approximate("5134924"); // "5.1M"
28+
```
29+
30+
Rounds numbers greater than 1000, up to the millions.
31+
32+
### Round to decimal place
33+
34+
Rounds a number to a given decimal place.
35+
36+
`roundToDecimalPlace(quant: number, roundTo: number): number`
37+
38+
#### Example
39+
40+
```js
41+
import { roundToDecimalPlace } from '@drivetribe/utils-number-formatters';
42+
43+
roundToDecimalPlace(12.34567, 1); // 12.3
44+
roundToDecimalPlace(12.34567, 2); // 12.35
45+
```

utils/number-formatters/package.json

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
{
2+
"name": "@drivetribe/utils-number-formatters",
3+
"version": "1.0.0",
4+
"description": "Selection of simple tools to format numbers for display purposes",
5+
"main": "lib/index.js",
6+
"scripts": {
7+
"build": "npm run lint && npm run test && babel src --out-dir lib",
8+
"semantic-release": "semantic-release pre && npm publish && semantic-release post",
9+
"test": "mocha --compilers js:babel-register",
10+
"lint": "eslint src"
11+
},
12+
"repository": {
13+
"type": "git",
14+
"url": "https://github.com/drivetribe/javascript-packages/"
15+
},
16+
"author": "Matt Perry",
17+
"license": "ISC",
18+
"devDependencies": {
19+
"babel-cli": "^6.9.0",
20+
"babel-eslint": "^6.0.4",
21+
"babel-preset-es2015": "^6.9.0",
22+
"babel-preset-react": "^6.5.0",
23+
"babel-preset-stage-2": "^6.5.0",
24+
"babel-register": "^6.9.0",
25+
"eslint": "^2.10.2",
26+
"eslint-config-airbnb": "^9.0.1",
27+
"eslint-plugin-flowtype": "^2.2.7",
28+
"eslint-plugin-import": "^1.8.0",
29+
"eslint-plugin-jsx-a11y": "^1.2.0",
30+
"eslint-plugin-react": "^5.1.1",
31+
"semantic-release": "^4.3.5"
32+
}
33+
}

utils/number-formatters/src/index.js

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
const MILLION = 1000000;
2+
const THOUSAND = 1000;
3+
const MILLION_THRESHOLD = MILLION * 0.99;
4+
5+
/**
6+
* Round a number to the given number of decimal places
7+
* @param {number} num Number to round
8+
* @param {number} roundTo Round to this many places (Default: 2)
9+
* @return {number} Rounded number
10+
*/
11+
export function roundToDecimalPlace(num, roundTo = 2) {
12+
const factor = 10 * roundTo;
13+
return Math.round(num * factor) / factor;
14+
}
15+
16+
/**
17+
* Convert a large number to a display-friendly approximation.
18+
* @param {number||string} num Number to convert
19+
* @return {string} Approximated number
20+
*/
21+
export function approximate(num) {
22+
const parsedNum = (typeof num === 'string') ? parseInt(num, 10) : num;
23+
24+
// Between 1,000 and 1,000,000
25+
if (parsedNum >= THOUSAND && parsedNum < MILLION_THRESHOLD) {
26+
return roundToDecimalPlace(parsedNum / THOUSAND, 1) + 'K';
27+
28+
// Above 1,000,000
29+
} else if (parsedNum >= MILLION_THRESHOLD) {
30+
return roundToDecimalPlace(parsedNum / MILLION, 1) + 'M';
31+
}
32+
33+
return `${parsedNum}`;
34+
}

utils/number-formatters/test/test.js

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import chai from 'chai';
2+
import {
3+
approximate,
4+
roundToDecimalPlace
5+
} from '../src';
6+
7+
const { expect } = chai;
8+
9+
describe('approximate()', () => {
10+
it('should accept both strings and numbers', () => {
11+
expect(approximate("0")).to.equal("0");
12+
expect(approximate(0)).to.equal("0");
13+
});
14+
15+
it('should not approximate numbers under a thousand', () => {
16+
expect(approximate(100)).to.equal("100");
17+
expect(approximate(999)).to.equal("999");
18+
});
19+
20+
it('should approximate numbers above 1000 and under 990000 to the closest thousand', () => {
21+
expect(approximate(1000)).to.equal("1K");
22+
expect(approximate(989999)).to.equal("990K");
23+
});
24+
25+
it('should approximate numbers above 990000 to the closest million', () => {
26+
expect(approximate(990000)).to.equal("1M");
27+
});
28+
29+
it('should round up to one decimal place and not show that decimal if it is a zero', () => {
30+
expect(approximate(1449)).to.equal("1.4K");
31+
expect(approximate(1450)).to.equal("1.5K");
32+
expect(approximate(10560000)).to.equal("10.6M");
33+
expect(approximate(10990000)).to.equal("11M");
34+
});
35+
});
36+
37+
describe('roundToDecimalPlace()', () => {
38+
const TEST_NUMBER = 12.34567;
39+
40+
it('should round a number to the given number of decimal places', () => {
41+
expect(roundToDecimalPlace(TEST_NUMBER, 1)).to.equal(12.3);
42+
expect(roundToDecimalPlace(TEST_NUMBER, 2)).to.equal(12.35);
43+
});
44+
45+
it('should round to 2 decimal places by default', () => {
46+
expect(roundToDecimalPlace(TEST_NUMBER)).to.equal(12.35);
47+
});
48+
});

0 commit comments

Comments
 (0)