mirror of
https://github.com/actualbudget/actual.git
synced 2026-03-11 20:44:32 -05:00
fix: Handle unicode minus in number parsing (#6247)
* fix(core): handle unicode minus in number parsing Fixes #6206. Added support for Unicode minus (U+2212) in looselyParseAmount, currencyToAmount, and stringToInteger. Added unit tests. * Refactor: Improve currency parsing logic Co-authored-by: matiss <matiss@mja.lv> * Refactor: Simplify currency parsing logic Co-authored-by: matiss <matiss@mja.lv> * [autofix.ci] apply automated fixes * fix: Handle Unicode minus inside parentheses correctly Fixed bug where amounts with both parentheses and Unicode minus (e.g., (−3.45)) were parsed as null instead of negative numbers. The Unicode minus is now removed from within parentheses before the parentheses-to-minus conversion, preventing double minus signs that caused parseFloat to return NaN. Added test cases for parenthesized amounts containing Unicode minus. * Add release notes for PR #6247 --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
809ab503d7
commit
43970c14b1
@@ -3,6 +3,7 @@ import {
|
||||
getNumberFormat,
|
||||
setNumberFormat,
|
||||
currencyToAmount,
|
||||
stringToInteger,
|
||||
titleFirst,
|
||||
} from './util';
|
||||
|
||||
@@ -49,11 +50,18 @@ describe('utility functions', () => {
|
||||
expect(looselyParseAmount('-3')).toBe(-3);
|
||||
expect(looselyParseAmount('-3.45')).toBe(-3.45);
|
||||
expect(looselyParseAmount('-3,45')).toBe(-3.45);
|
||||
// Unicode minus
|
||||
expect(looselyParseAmount('−3')).toBe(-3);
|
||||
expect(looselyParseAmount('−3.45')).toBe(-3.45);
|
||||
expect(looselyParseAmount('−3,45')).toBe(-3.45);
|
||||
});
|
||||
|
||||
test('looseParseAmount works with parentheses (negative)', () => {
|
||||
expect(looselyParseAmount('(3.45)')).toBe(-3.45);
|
||||
expect(looselyParseAmount('(3)')).toBe(-3);
|
||||
// Parentheses with Unicode minus
|
||||
expect(looselyParseAmount('(−3.45)')).toBe(-3.45);
|
||||
expect(looselyParseAmount('(−3)')).toBe(-3);
|
||||
});
|
||||
|
||||
test('looseParseAmount ignores non-numeric characters', () => {
|
||||
@@ -142,6 +150,10 @@ describe('utility functions', () => {
|
||||
expect(currencyToAmount('-3')).toBe(-3);
|
||||
expect(currencyToAmount('-3.45')).toBe(-3.45);
|
||||
expect(currencyToAmount('-3,45')).toBe(-3.45);
|
||||
// Unicode minus
|
||||
expect(currencyToAmount('−3')).toBe(-3);
|
||||
expect(currencyToAmount('−3.45')).toBe(-3.45);
|
||||
expect(currencyToAmount('−3,45')).toBe(-3.45);
|
||||
});
|
||||
|
||||
test('currencyToAmount works with non-fractional numbers', () => {
|
||||
@@ -181,4 +193,10 @@ describe('utility functions', () => {
|
||||
expect(titleFirst('a')).toBe('A');
|
||||
expect(titleFirst('abc')).toBe('Abc');
|
||||
});
|
||||
|
||||
test('stringToInteger works with negative numbers', () => {
|
||||
expect(stringToInteger('-3')).toBe(-3);
|
||||
// Unicode minus
|
||||
expect(stringToInteger('−3')).toBe(-3);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -461,6 +461,8 @@ export function amountToCurrencyNoDecimal(amount: Amount): CurrencyAmount {
|
||||
}
|
||||
|
||||
export function currencyToAmount(currencyAmount: string): Amount | null {
|
||||
currencyAmount = currencyAmount.replace(/\u2212/g, '-');
|
||||
|
||||
let integer, fraction;
|
||||
|
||||
// match the last dot or comma in the string
|
||||
@@ -490,7 +492,9 @@ export function currencyToInteger(
|
||||
}
|
||||
|
||||
export function stringToInteger(str: string): number | null {
|
||||
const amount = parseInt(str.replace(/[^-0-9.,]/g, ''));
|
||||
const amount = parseInt(
|
||||
str.replace(/\u2212/g, '-').replace(/[^-0-9.,]/g, ''),
|
||||
);
|
||||
if (!isNaN(amount)) {
|
||||
return amount;
|
||||
}
|
||||
@@ -536,7 +540,12 @@ export function looselyParseAmount(amount: string) {
|
||||
}
|
||||
|
||||
if (amount.startsWith('(') && amount.endsWith(')')) {
|
||||
// Remove Unicode minus inside parentheses before converting to ASCII minus
|
||||
amount = amount.replace(/\u2212/g, '');
|
||||
amount = amount.replace('(', '-').replace(')', '');
|
||||
} else {
|
||||
// Replace Unicode minus with ASCII minus for non-parenthesized amounts
|
||||
amount = amount.replace(/\u2212/g, '-');
|
||||
}
|
||||
|
||||
// Look for a decimal marker, then look for either 1-2 or 4-9 decimal places.
|
||||
|
||||
7
upcoming-release-notes/6247.md
Normal file
7
upcoming-release-notes/6247.md
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
category: Bugfix
|
||||
authors: [MatissJanis]
|
||||
---
|
||||
|
||||
Fix number parsing to recognize Unicode minus as a valid negative indicator.
|
||||
|
||||
Reference in New Issue
Block a user