Skip to content

Commit

Permalink
feat(currency): add currency support
Browse files Browse the repository at this point in the history
  • Loading branch information
jlozovei committed May 2, 2020
1 parent 7835c2a commit b31eda6
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 35 deletions.
15 changes: 7 additions & 8 deletions src/convert.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,16 @@ import isSafeNumber from './helpers/isSafeNumber';

import generateWords from './generateWords';

const convert = (params) => {
const { value, lang } = params;
const num = parseInt(value, 10);
const convert = (options) => {
const { value, lang } = options;

if (!isFinite(num)) {
/* if (!isFinite(num)) {
throw new TypeError('Not a finite number: ' + value + ' (' + typeof value + ')');
}
} */

if (!isSafeNumber(num)) {
/* if (!isSafeNumber(num)) {
throw new RangeError('Input is not a safe number, it’s either too large or too small.');
}
} */

try {
const locale = require(`./languages/${lang}.json`);
Expand All @@ -27,7 +26,7 @@ const convert = (params) => {
`);
}

return generateWords(num, lang);
return generateWords(options);
};

export default convert;
101 changes: 74 additions & 27 deletions src/generateWords.js
Original file line number Diff line number Diff line change
@@ -1,109 +1,156 @@
import isFloat from './helpers/isFloat';
import getDecimals from './helpers/getDecimals';
import padNumber from './helpers/padNumber';

import { scale } from './constants/index';

const state = {};

function floor(expression) {
return Math.floor(expression);
}

function generateWords(number, lang, lastWords) {
function wordify(number, lastWords) {
let word = '';
let words = lastWords;
let remainder = 0;

const locale = require(`./languages/${lang}.json`);

if (number === 0) return !words ? locale.LESS_THAN_TWENTY[0] : words.join(' ').replace(/,$/, '');
if (number === 0)
return !words ? state.locale.LESS_THAN_TWENTY[0] : words.join(' ').replace(/,$/, '');

if (!words) words = [];

if (number < scale.TWENTY) {
word = locale.LESS_THAN_TWENTY[number];
word = state.locale.LESS_THAN_TWENTY[number];
} else {
if (number < scale.ONE_HUNDRED) {
remainder = number % scale.TEN;
word = locale.DOZENS[floor(number / scale.TEN)];
word = state.locale.DOZENS[floor(number / scale.TEN)];

if (remainder) {
word += `${locale.PUNCTUATION.dozens}${locale.LESS_THAN_TWENTY[remainder]}`;
word += `${state.locale.PUNCTUATION.dozens}${state.locale.LESS_THAN_TWENTY[remainder]}`;
remainder = 0;
}
} else if (number < scale.ONE_THOUSAND) {
const factor = floor(number / scale.ONE_HUNDRED);
remainder = number % scale.ONE_HUNDRED;

if (remainder) {
word = `${locale.HUNDREDS[factor].plural} ${locale.PUNCTUATION.hundreds}`;
word = `${state.locale.HUNDREDS[factor].plural} ${state.locale.PUNCTUATION.hundreds}`;
} else {
word = locale.HUNDREDS[factor].singular;
word = state.locale.HUNDREDS[factor].singular;
}
} else if (number < scale.ONE_MILLION) {
const factor = floor(number / scale.ONE_THOUSAND);
remainder = number % scale.ONE_THOUSAND;
word = `${generateWords(floor(number / scale.ONE_THOUSAND), lang)} `;
word = `${wordify(floor(number / scale.ONE_THOUSAND))} `;

if (remainder) {
word += locale.SHORT_SCALE_NAME.thousand.plural;
word += state.locale.SHORT_SCALE_NAME.thousand.plural;
} else {
word += locale.SHORT_SCALE_NAME.thousand.singular;
word += state.locale.SHORT_SCALE_NAME.thousand.singular;
}

if ((remainder / scale.TEN) % scale.TEN === 0) {
word += ` ${locale.PUNCTUATION.hundreds}`;
word += ` ${state.locale.PUNCTUATION.hundreds}`;
} else {
word += ',';
}
} else if (number < scale.ONE_BILLION) {
const factor = floor(number / scale.ONE_MILLION);
remainder = number % scale.ONE_MILLION;
word = `${generateWords(floor(number / scale.ONE_MILLION), lang)} `;
word = `${wordify(floor(number / scale.ONE_MILLION))} `;

if (remainder) {
word += locale.SHORT_SCALE_NAME.million.plural;
word += state.locale.SHORT_SCALE_NAME.million.plural;
} else {
word += locale.SHORT_SCALE_NAME.million.singular;
word += state.locale.SHORT_SCALE_NAME.million.singular;
}

word += ',';
} else if (number < scale.ONE_TRILLION) {
const factor = floor(number / scale.ONE_BILLION);
remainder = number % scale.ONE_BILLION;
word = `${generateWords(floor(number / scale.ONE_BILLION), lang)} `;
word = `${wordify(floor(number / scale.ONE_BILLION))} `;

if (remainder) {
word += locale.SHORT_SCALE_NAME.billion.plural;
word += state.locale.SHORT_SCALE_NAME.billion.plural;
} else {
word += locale.SHORT_SCALE_NAME.billion.singular;
word += state.locale.SHORT_SCALE_NAME.billion.singular;
}

word += ',';
} else if (number < scale.ONE_QUADRILLION) {
const factor = floor(number / scale.ONE_TRILLION);
remainder = number % scale.ONE_TRILLION;
word = `${generateWords(floor(number / scale.ONE_TRILLION), lang)} `;
word = `${wordify(floor(number / scale.ONE_TRILLION))} `;

if (remainder) {
word += locale.SHORT_SCALE_NAME.trillion.plural;
word += state.locale.SHORT_SCALE_NAME.trillion.plural;
} else {
word += locale.SHORT_SCALE_NAME.trillion.singular;
word += state.locale.SHORT_SCALE_NAME.trillion.singular;
}

word += ',';
} else if (number <= scale.MAX_NUMBER) {
const factor = floor(number / scale.ONE_QUADRILLION);
remainder = number % scale.ONE_QUADRILLION;
word = `${generateWords(floor(number / scale.ONE_QUADRILLION), lang)} `;
word = `${wordify(floor(number / scale.ONE_QUADRILLION))} `;

if (remainder) {
word += locale.SHORT_SCALE_NAME.quadrillion.plural;
word += state.locale.SHORT_SCALE_NAME.quadrillion.plural;
} else {
word += locale.SHORT_SCALE_NAME.quadrillion.singular;
word += state.locale.SHORT_SCALE_NAME.quadrillion.singular;
}

word += ',';
}
}

words.push(word);
return generateWords(remainder, lang, words);
return wordify(remainder, words);
}

export default generateWords;
export default function generateWords(options) {
const { value, lang, currency } = options;
const hasDecimalValues = isFloat(value);

const locale = require(`./languages/${lang}.json`);
state.locale = locale;

if (currency) {
state.currency = currency;
}

if (hasDecimalValues) {
const decimals = getDecimals(value, 10);
const padded = padNumber(decimals);

state.decimals = {
value: padded,
words: wordify(parseInt(padded))
};
} else {
delete state.decimals;
}

const number = parseInt(value, 10);
let words = wordify(number);

if (state.currency) {
if (number > 1) words += ` ${state.currency.name.plural}`;
else words += ` ${state.currency.name.singular}`;

if (state.decimals) {
words += ` ${state.locale.PUNCTUATION.decimals} ${state.decimals.words}`;

if (state.decimals.value > 1) {
words += ` ${state.currency.decimals.plural}`;
} else {
words += ` ${state.currency.decimals.singular}`;
}
}
}

return words;
}
3 changes: 3 additions & 0 deletions src/helpers/getDecimals.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default function getDecimals(number) {
return (number + '').split('.')[1];
}
3 changes: 3 additions & 0 deletions src/helpers/isFloat.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default function isFloat(number) {
return Number(number) === number && number % 1 !== 0;
}
12 changes: 12 additions & 0 deletions src/helpers/padNumber.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export default function padNumber(number) {
let pad;
const numberAsString = number + '';

if (numberAsString.length >= 2) {
pad = numberAsString.substring(0, 2);
} else {
pad = `${numberAsString}0`;
}

return pad;
}

0 comments on commit b31eda6

Please sign in to comment.