[go: nahoru, domu]

Skip to content

Commit

Permalink
fix(toDecimal): preserve negative sign for leading zeros
Browse files Browse the repository at this point in the history
Change dinerojs#690 fixed the general case of formatting negative unit values,
but was one remaining case where formatting was still incorrect: when
the first unit is -0, the resulting string didn't include the leading
negative sign.

This change identifies that exact case (negative value, leading zero)
and pads the resulting string with a leading negative sign.

Fixes dinerojs#692
  • Loading branch information
jparise committed Dec 11, 2022
1 parent c5b9173 commit 0961248
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 3 deletions.
17 changes: 14 additions & 3 deletions packages/core/src/api/toDecimal.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { NON_DECIMAL_CURRENCY_MESSAGE } from '../checks';
import { assert } from '../helpers';
import type { Calculator, Dinero, Formatter, Transformer } from '../types';
import { absolute, computeBase, equal, isArray } from '../utils';
import { absolute, computeBase, equal, isArray, lessThan } from '../utils';

import { toUnits } from './toUnits';

Expand Down Expand Up @@ -49,12 +49,17 @@ function getDecimal<TAmount>(
formatter: Formatter<TAmount>
) {
const absoluteFn = absolute(calculator);
const equalFn = equal(calculator);
const lessThanFn = lessThan(calculator);
const zero = calculator.zero();

return (units: readonly TAmount[], scale: TAmount) => {
return units
const lastIndex = units.length - 1;

const decimalString = units
.map((unit, index) => {
const isFirst = index === 0;
const isLast = units.length - 1 === index;
const isLast = lastIndex === index;

const unitAsString = formatter.toString(
isFirst ? unit : absoluteFn(unit)
Expand All @@ -67,5 +72,11 @@ function getDecimal<TAmount>(
return unitAsString;
})
.join('.');

// A leading negative zero is a special case because the toString
// formatter (generally String) won't preserve its negative sign.
return equalFn(units[0], zero) && lessThanFn(units[lastIndex], zero)
? `-${decimalString}`
: decimalString;
};
}
30 changes: 30 additions & 0 deletions packages/dinero.js/src/api/__tests__/toDecimal.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,16 @@ describe('toDecimal', () => {

expect(toDecimal(d)).toEqual('-10.50');
});
it('returns the negative amount with a leading zero in decimal format', () => {
const d = dinero({ amount: -1, currency: USD });

expect(toDecimal(d)).toEqual('-0.01');
});
it('returns negative zero amount as a positive value in decimal format', () => {
const d = dinero({ amount: -0, currency: USD });

expect(toDecimal(d)).toEqual('0.00');
});
it('uses a custom transformer', () => {
const d = dinero({ amount: 1050, currency: USD });

Expand Down Expand Up @@ -118,6 +128,16 @@ describe('toDecimal', () => {

expect(toDecimal(d)).toEqual('-10.50');
});
it('returns the negative amount with a leading zero in decimal format', () => {
const d = dinero({ amount: -1n, currency: bigintUSD });

expect(toDecimal(d)).toEqual('-0.01');
});
it('returns negative zero amount as a positive value in decimal format', () => {
const d = dinero({ amount: -0n, currency: bigintUSD });

expect(toDecimal(d)).toEqual('0.00');
});
it('uses a custom transformer', () => {
const d = dinero({ amount: 1050n, currency: bigintUSD });

Expand Down Expand Up @@ -198,6 +218,16 @@ describe('toDecimal', () => {

expect(toDecimal(d)).toEqual('-10.05');
});
it('returns the negative amount with a leading zero in decimal format', () => {
const d = dinero({ amount: new Big(-1), currency: bigjsUSD });

expect(toDecimal(d)).toEqual('-0.01');
});
it('returns negative zero amount as a positive value in decimal format', () => {
const d = dinero({ amount: new Big(-0), currency: bigjsUSD });

expect(toDecimal(d)).toEqual('0.00');
});
it('uses a custom transformer', () => {
const d = dinero({ amount: new Big(1050), currency: bigjsUSD });

Expand Down

0 comments on commit 0961248

Please sign in to comment.