Skip to content

Commit

Permalink
Added currencyFormat utility
Browse files Browse the repository at this point in the history
  • Loading branch information
runely committed Apr 5, 2022
1 parent 5d95e98 commit 5e86fb4
Show file tree
Hide file tree
Showing 6 changed files with 340 additions and 0 deletions.
59 changes: 59 additions & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,64 @@ declare const _exports: {
style?: "long" | "short" | "narrow";
};
}): string;
currencyFormat(options: {
/**
* Number to format
*/
number: number;
/**
* Locale to format number into (Default = 'en')
*/
locale?: string;
/**
* CurrencyFormat options
*/
options?: {
/**
* Only used when notation is "compact" (Default = "short")
*/
compactDisplay?: "long" | "short";
/**
* The currency to use in currency formatting. Possible values are the ISO 4217 currency codes, such as "USD" for the US dollar, "EUR"
*/
currency: string;
/**
* In many locales, accounting format means to wrap the number with parentheses instead of appending a minus sign. You can enable this formatting by setting the currencySign option to "accounting". The default value is "standard"
*/
currencySign?: "standard" | "accounting";
/**
* The minimum number of fraction digits to use. Possible values are from 0 to 20 (Default = 0)
*/
minimumFractionDigits?: number;
/**
* The maximum number of fraction digits to use. Possible values are from 0 to 20 (the default for plain number formatting is the larger of minimumFractionDigits and 3)
*/
maximumFractionDigits?: number;
/**
* The minimum number of significant digits to use. Possible values are from 1 to 21 (Default = 1)
*/
minimumSignificantDigits?: number;
/**
* The maximum number of significant digits to use. Possible values are from 1 to 21 (Default = 21)
*/
maximumSignificantDigits?: number;
/**
* The minimum number of integer digits to use. Possible values are from 1 to 21 (Default = 1)
*/
minimumIntegerDigits?: number;
/**
* The formatting that should be displayed for the number (Default = "standard")
*/
notation: "standard" | "compact" | "scientific" | "engineering";
/**
* When to display the sign for the number (Default = "auto")
*/
signDisplay: "always" | "auto" | "exceptZero" | "never";
/**
* The unit formatting style to use in unit formatting (Default = "short")
*/
unitDisplay: "long" | "short" | "narrow";
};
}): string;
};
export = _exports;
85 changes: 85 additions & 0 deletions lib/utilities.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,4 +82,89 @@ declare class Utilities {
style?: "long" | "short" | "narrow";
};
}): string;
/**
* @typedef {Object} FormatCurrencyOptions
* @property {Number} number Number to format
* @property {String} [locale] Locale to format number into (Default = 'en')
* @property {CurrencyFormatOptions} [options] CurrencyFormat options
*/
/**
* CurrencyFormat options
* @typedef {Object} CurrencyFormatOptions
* @property {"long"|"short"} [compactDisplay] Only used when notation is "compact" (Default = "short")
* @property {String} currency The currency to use in currency formatting. Possible values are the ISO 4217 currency codes, such as "USD" for the US dollar, "EUR"
* @property {"standard"|"accounting"} [currencySign] In many locales, accounting format means to wrap the number with parentheses instead of appending a minus sign. You can enable this formatting by setting the currencySign option to "accounting". The default value is "standard"
* @property {Number} [minimumFractionDigits] The minimum number of fraction digits to use. Possible values are from 0 to 20 (Default = 0)
* @property {Number} [maximumFractionDigits] The maximum number of fraction digits to use. Possible values are from 0 to 20 (the default for plain number formatting is the larger of minimumFractionDigits and 3)
* @property {Number} [minimumSignificantDigits] The minimum number of significant digits to use. Possible values are from 1 to 21 (Default = 1)
* @property {Number} [maximumSignificantDigits] The maximum number of significant digits to use. Possible values are from 1 to 21 (Default = 21)
* @property {Number} [minimumIntegerDigits] The minimum number of integer digits to use. Possible values are from 1 to 21 (Default = 1)
* @property {"compact"|"standard"|"scientific"|"engineering"} notation The formatting that should be displayed for the number (Default = "standard")
* @property {"always"|"exceptZero"|"auto"|"never"} signDisplay When to display the sign for the number (Default = "auto")
* @property {"long"|"short"|"narrow"} unitDisplay The unit formatting style to use in unit formatting (Default = "short")
*/
/**
* Format number in currency
* @param {FormatCurrencyOptions} options FormatCurrency options
* @returns {String} The formatted string
*/
static currencyFormat(options: {
/**
* Number to format
*/
number: number;
/**
* Locale to format number into (Default = 'en')
*/
locale?: string;
/**
* CurrencyFormat options
*/
options?: {
/**
* Only used when notation is "compact" (Default = "short")
*/
compactDisplay?: "long" | "short";
/**
* The currency to use in currency formatting. Possible values are the ISO 4217 currency codes, such as "USD" for the US dollar, "EUR"
*/
currency: string;
/**
* In many locales, accounting format means to wrap the number with parentheses instead of appending a minus sign. You can enable this formatting by setting the currencySign option to "accounting". The default value is "standard"
*/
currencySign?: "standard" | "accounting";
/**
* The minimum number of fraction digits to use. Possible values are from 0 to 20 (Default = 0)
*/
minimumFractionDigits?: number;
/**
* The maximum number of fraction digits to use. Possible values are from 0 to 20 (the default for plain number formatting is the larger of minimumFractionDigits and 3)
*/
maximumFractionDigits?: number;
/**
* The minimum number of significant digits to use. Possible values are from 1 to 21 (Default = 1)
*/
minimumSignificantDigits?: number;
/**
* The maximum number of significant digits to use. Possible values are from 1 to 21 (Default = 21)
*/
maximumSignificantDigits?: number;
/**
* The minimum number of integer digits to use. Possible values are from 1 to 21 (Default = 1)
*/
minimumIntegerDigits?: number;
/**
* The formatting that should be displayed for the number (Default = "standard")
*/
notation: "compact" | "standard" | "scientific" | "engineering";
/**
* When to display the sign for the number (Default = "auto")
*/
signDisplay: "always" | "exceptZero" | "auto" | "never";
/**
* The unit formatting style to use in unit formatting (Default = "short")
*/
unitDisplay: "long" | "short" | "narrow";
};
}): string;
}
33 changes: 33 additions & 0 deletions lib/utilities.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
Import dependencies
*/
const { formatRelativeDate } = require('../util/relative-date-format')
const { formatCurrency } = require('../util/currency-format')

module.exports = class Utilities {
/**
Expand Down Expand Up @@ -150,4 +151,36 @@ module.exports = class Utilities {
static relativeDateFormat (options) {
return formatRelativeDate(options)
}

/**
* @typedef {Object} FormatCurrencyOptions
* @property {Number} number Number to format
* @property {String} [locale] Locale to format number into (Default = 'en')
* @property {CurrencyFormatOptions} [options] CurrencyFormat options
*/

/**
* CurrencyFormat options
* @typedef {Object} CurrencyFormatOptions
* @property {"long"|"short"} [compactDisplay] Only used when notation is "compact" (Default = "short")
* @property {String} currency The currency to use in currency formatting. Possible values are the ISO 4217 currency codes, such as "USD" for the US dollar, "EUR"
* @property {"standard"|"accounting"} [currencySign] In many locales, accounting format means to wrap the number with parentheses instead of appending a minus sign. You can enable this formatting by setting the currencySign option to "accounting". The default value is "standard"
* @property {Number} [minimumFractionDigits] The minimum number of fraction digits to use. Possible values are from 0 to 20 (Default = 0)
* @property {Number} [maximumFractionDigits] The maximum number of fraction digits to use. Possible values are from 0 to 20 (the default for plain number formatting is the larger of minimumFractionDigits and 3)
* @property {Number} [minimumSignificantDigits] The minimum number of significant digits to use. Possible values are from 1 to 21 (Default = 1)
* @property {Number} [maximumSignificantDigits] The maximum number of significant digits to use. Possible values are from 1 to 21 (Default = 21)
* @property {Number} [minimumIntegerDigits] The minimum number of integer digits to use. Possible values are from 1 to 21 (Default = 1)
* @property {"compact"|"standard"|"scientific"|"engineering"} notation The formatting that should be displayed for the number (Default = "standard")
* @property {"always"|"exceptZero"|"auto"|"never"} signDisplay When to display the sign for the number (Default = "auto")
* @property {"long"|"short"|"narrow"} unitDisplay The unit formatting style to use in unit formatting (Default = "short")
*/

/**
* Format number in currency
* @param {FormatCurrencyOptions} options FormatCurrency options
* @returns {String} The formatted string
*/
static currencyFormat (options) {
return formatCurrency(options)
}
}
55 changes: 55 additions & 0 deletions tests/util/currency-format.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
const { formatCurrency } = require('../../util/currency-format')

describe('formatCurrency', () => {
test('no arguments passed - should throw error', () => {
expect(() => formatCurrency()).toThrow()
})

describe('currency as', () => {
test('"NOK"', () => {
const formatted = formatCurrency({ number: 69, options: { currency: 'NOK' } })
expect(formatted === 'NOK 69.00').toBeTruthy()
})

test('"USD"', () => {
const formatted = formatCurrency({ number: 69, options: { currency: 'USD' } })
expect(formatted === '$69.00').toBeTruthy()
})
})

describe('minimumFractionDigits', () => {
test('as 5', () => {
const formatted = formatCurrency({ number: 69, options: { currency: 'NOK', minimumFractionDigits: 5 } })
expect(formatted === 'NOK 69.00000').toBeTruthy()
})

test('as 0', () => {
const formatted = formatCurrency({ number: 69, options: { currency: 'NOK', minimumFractionDigits: 0 } })
expect(formatted === 'NOK 69').toBeTruthy()
})
})

describe('minimumSignificantDigits', () => {
test('as 5', () => {
const formatted = formatCurrency({ number: 69, options: { currency: 'NOK', minimumSignificantDigits: 5 } })
expect(formatted === 'NOK 69.000').toBeTruthy()
})

test('as 1', () => {
const formatted = formatCurrency({ number: 69, options: { currency: 'NOK', minimumSignificantDigits: 1 } })
expect(formatted === 'NOK 69').toBeTruthy()
})
})

describe('minimumIntegerDigits', () => {
test('as 5', () => {
const formatted = formatCurrency({ number: 69, options: { currency: 'NOK', minimumIntegerDigits: 5 } })
expect(formatted === 'NOK 00,069.00').toBeTruthy()
})

test('as 1', () => {
const formatted = formatCurrency({ number: 69, options: { currency: 'NOK', minimumIntegerDigits: 1 } })
expect(formatted === 'NOK 69.00').toBeTruthy()
})
})
})
64 changes: 64 additions & 0 deletions util/currency-format.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
export function formatCurrency({ number, locale, options }: FormatCurrencyOptions): string;
export type FormatCurrencyOptions = {
/**
* Number to format
*/
number: number;
/**
* Locale to format number into (Default = 'en')
*/
locale?: string;
/**
* CurrencyFormat options
*/
options?: CurrencyFormatOptions;
};
/**
* CurrencyFormat options
*/
export type CurrencyFormatOptions = {
/**
* Only used when notation is "compact" (Default = "short")
*/
compactDisplay?: "long" | "short";
/**
* The currency to use in currency formatting. Possible values are the ISO 4217 currency codes, such as "USD" for the US dollar, "EUR"
*/
currency: string;
/**
* In many locales, accounting format means to wrap the number with parentheses instead of appending a minus sign. You can enable this formatting by setting the currencySign option to "accounting". The default value is "standard"
*/
currencySign?: "standard" | "accounting";
/**
* The minimum number of fraction digits to use. Possible values are from 0 to 20 (Default = 0)
*/
minimumFractionDigits?: number;
/**
* The maximum number of fraction digits to use. Possible values are from 0 to 20 (the default for plain number formatting is the larger of minimumFractionDigits and 3)
*/
maximumFractionDigits?: number;
/**
* The minimum number of significant digits to use. Possible values are from 1 to 21 (Default = 1)
*/
minimumSignificantDigits?: number;
/**
* The maximum number of significant digits to use. Possible values are from 1 to 21 (Default = 21)
*/
maximumSignificantDigits?: number;
/**
* The minimum number of integer digits to use. Possible values are from 1 to 21 (Default = 1)
*/
minimumIntegerDigits?: number;
/**
* The formatting that should be displayed for the number (Default = "standard")
*/
notation: "compact" | "standard" | "scientific" | "engineering";
/**
* When to display the sign for the number (Default = "auto")
*/
signDisplay: "always" | "exceptZero" | "auto" | "never";
/**
* The unit formatting style to use in unit formatting (Default = "short")
*/
unitDisplay: "long" | "short" | "narrow";
};
44 changes: 44 additions & 0 deletions util/currency-format.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/**
* @typedef {Object} FormatCurrencyOptions
* @property {Number} number Number to format
* @property {String} [locale] Locale to format number into (Default = 'en')
* @property {CurrencyFormatOptions} [options] CurrencyFormat options
*/

/**
* CurrencyFormat options
* @typedef {Object} CurrencyFormatOptions
* @property {"long"|"short"} [compactDisplay] Only used when notation is "compact" (Default = "short")
* @property {String} currency The currency to use in currency formatting. Possible values are the ISO 4217 currency codes, such as "USD" for the US dollar, "EUR"
* @property {"standard"|"accounting"} [currencySign] In many locales, accounting format means to wrap the number with parentheses instead of appending a minus sign. You can enable this formatting by setting the currencySign option to "accounting". The default value is "standard"
* @property {Number} [minimumFractionDigits] The minimum number of fraction digits to use. Possible values are from 0 to 20 (Default = 0)
* @property {Number} [maximumFractionDigits] The maximum number of fraction digits to use. Possible values are from 0 to 20 (the default for plain number formatting is the larger of minimumFractionDigits and 3)
* @property {Number} [minimumSignificantDigits] The minimum number of significant digits to use. Possible values are from 1 to 21 (Default = 1)
* @property {Number} [maximumSignificantDigits] The maximum number of significant digits to use. Possible values are from 1 to 21 (Default = 21)
* @property {Number} [minimumIntegerDigits] The minimum number of integer digits to use. Possible values are from 1 to 21 (Default = 1)
* @property {"compact"|"standard"|"scientific"|"engineering"} notation The formatting that should be displayed for the number (Default = "standard")
* @property {"always"|"exceptZero"|"auto"|"never"} signDisplay When to display the sign for the number (Default = "auto")
* @property {"long"|"short"|"narrow"} unitDisplay The unit formatting style to use in unit formatting (Default = "short")
*/

/**
* Format currency
* @param {String} locale Locale to format currency into
* @param {CurrencyFormatOptions} options CurrencyFormat options
* @returns {String}
*/
const getCurrencyFormatter = (locale, options) => {
return new Intl.NumberFormat(locale, { ...options, style: 'currency' })
}

/**
* Format number in currency
* @param {FormatCurrencyOptions} options FormatCurrency options
* @returns {String} The formatted string
*/
module.exports.formatCurrency = ({ number, locale = 'en', options = undefined }) => {
if (Number.isNaN(number)) throw new Error('Pass a number')

const FORMATTER = getCurrencyFormatter(locale, options)
return FORMATTER.format(number).replace('\xa0', ' ') // replace char code 160 ( ) with regular space
}

0 comments on commit 5e86fb4

Please sign in to comment.