Skip to content

Commit

Permalink
#731 - amount parser should respect grouping separators
Browse files Browse the repository at this point in the history
  • Loading branch information
deadlocker8 committed Feb 13, 2023
1 parent bd968ab commit 35daa09
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public CsvTransaction createCsvTransactionFromCsvRow(CsvRow csvRow, CsvColumnSet
final String description = csvRow.getColumns().get(csvColumnSettings.columnDescription() - 1);

final String amount = csvRow.getColumns().get(csvColumnSettings.columnAmount() - 1);
final Optional<Integer> parsedAmountOptional = AmountParser.parse(amount);
final Optional<Integer> parsedAmountOptional = AmountParser.parse(amount, '.', ',');
if(parsedAmountOptional.isEmpty())
{
throw new CsvTransactionParseException(Localization.getString("transactions.import.error.parse.amount", index + 1));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
package de.deadlocker8.budgetmaster.transactions.csvimport;

import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.MessageFormat;
import java.text.ParseException;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class AmountParser
{
private static final Pattern PATTERN_AMOUNT = Pattern.compile("^\\s*([-+]?)\\s*(\\d+(,\\d+)?(\\.\\d+)?)");
private static final Pattern PATTERN_AMOUNT = Pattern.compile("^\\s*([-+]?)\\s*(\\d+(.*\\d+)?)");

private AmountParser()
{
}

public static Optional<Integer> parse(String amountString)
public static Optional<Integer> parse(String amountString, char decimalSeparator, char groupingSeparator)
{
if(amountString == null)
{
Expand All @@ -24,17 +27,28 @@ public static Optional<Integer> parse(String amountString)
boolean matchFound = matcher.find();
if(matchFound)
{
final String sign = matcher.group(1);
String amount = matcher.group(2);
amount = amount.replace(',', '.');
String sign = matcher.group(1);
if(sign.equals("+"))
{
sign = "";
}

final String amount = matcher.group(2);

final DecimalFormat decimalFormat = new DecimalFormat();
final DecimalFormatSymbols symbols = new DecimalFormatSymbols();
symbols.setDecimalSeparator(decimalSeparator);
symbols.setGroupingSeparator(groupingSeparator);
decimalFormat.setNegativePrefix("-");
decimalFormat.setDecimalFormatSymbols(symbols);

final String parseableString = MessageFormat.format("{0}{1}", sign, amount);
try
{
final double parseDouble = Double.parseDouble(parseableString);
final double parseDouble = decimalFormat.parse(parseableString).doubleValue();
return Optional.of((int) (parseDouble * 100));
}
catch(NumberFormatException e)
catch(ParseException e)
{
return Optional.empty();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,196 +13,244 @@ class AmountParserTest
@Test
void test_dot_positive_noCurrency()
{
assertThat(AmountParser.parse("12.03"))
assertThat(AmountParser.parse("12.03", '.', ','))
.isPresent()
.get().isEqualTo(1203);
}

@Test
void test_dot_negative_noCurrency()
{
assertThat(AmountParser.parse("-18.41"))
assertThat(AmountParser.parse("-18.41", '.', ','))
.isPresent()
.get().isEqualTo(-1841);
}

@Test
void test_dot_negativeWithSpace_noCurrency()
{
assertThat(AmountParser.parse("- 200.30"))
assertThat(AmountParser.parse("- 200.30", '.', ','))
.isPresent()
.get().isEqualTo(-20030);
}

@Test
void test_dot_positive_currency()
{
assertThat(AmountParser.parse("12.03 €"))
assertThat(AmountParser.parse("12.03 €", '.', ','))
.isPresent()
.get().isEqualTo(1203);
}

@Test
void test_dot_negative_currency()
{
assertThat(AmountParser.parse("-18.41€"))
assertThat(AmountParser.parse("-18.41€", '.', ','))
.isPresent()
.get().isEqualTo(-1841);
}

@Test
void test_dot_positiveWithSign_noCurrency()
{
assertThat(AmountParser.parse("+12.03"))
assertThat(AmountParser.parse("+12.03", '.', ','))
.isPresent()
.get().isEqualTo(1203);
}

@Test
void test_dot_positiveWithSignWithSpace_noCurrency()
{
assertThat(AmountParser.parse("+ 12.03"))
assertThat(AmountParser.parse("+ 12.03", '.', ','))
.isPresent()
.get().isEqualTo(1203);
}

@Test
void test_comma_positive_noCurrency()
{
assertThat(AmountParser.parse("12,03"))
assertThat(AmountParser.parse("12,03", ',', '.'))
.isPresent()
.get().isEqualTo(1203);
}

@Test
void test_comma_negative_noCurrency()
{
assertThat(AmountParser.parse("-18,41"))
assertThat(AmountParser.parse("-18,41", ',', '.'))
.isPresent()
.get().isEqualTo(-1841);
}

@Test
void test_comma_negativeWithSpace_noCurrency()
{
assertThat(AmountParser.parse("- 200,30"))
assertThat(AmountParser.parse("- 200,30", ',', '.'))
.isPresent()
.get().isEqualTo(-20030);
}

@Test
void test_comma_positive_currency()
{
assertThat(AmountParser.parse("12,03 €"))
assertThat(AmountParser.parse("12,03 €", ',', '.'))
.isPresent()
.get().isEqualTo(1203);
}

@Test
void test_comma_negative_currency()
{
assertThat(AmountParser.parse("-18,41€"))
assertThat(AmountParser.parse("-18,41€", ',', '.'))
.isPresent()
.get().isEqualTo(-1841);
}

@Test
void test_comma_positiveWithSign_noCurrency()
{
assertThat(AmountParser.parse("+12,03"))
assertThat(AmountParser.parse("+12,03", ',', '.'))
.isPresent()
.get().isEqualTo(1203);
}

@Test
void test_comma_positiveWithSignWithSpace_noCurrency()
{
assertThat(AmountParser.parse("+12,03"))
assertThat(AmountParser.parse("+12,03", ',', '.'))
.isPresent()
.get().isEqualTo(1203);
}

@Test
void test_invalid_null()
{
assertThat(AmountParser.parse(null))
assertThat(AmountParser.parse(null, '.', ','))
.isEmpty();
}

@Test
void test_invalid_empty()
{
assertThat(AmountParser.parse(""))
assertThat(AmountParser.parse("", '.', ','))
.isEmpty();
}

@Test
void test_invalid_empty2()
{
assertThat(AmountParser.parse(" "))
assertThat(AmountParser.parse(" ", '.', ','))
.isEmpty();
}

@Test
void test_invalid()
{
assertThat(AmountParser.parse("abc.42€"))
assertThat(AmountParser.parse("abc.42€", '.', ','))
.isEmpty();
}

@Test
void test_integer_positive_noCurrency()
{
assertThat(AmountParser.parse("12"))
assertThat(AmountParser.parse("12", '.', ','))
.isPresent()
.get().isEqualTo(1200);
}

@Test
void test_integer_negative_noCurrency()
{
assertThat(AmountParser.parse("-18"))
assertThat(AmountParser.parse("-18", '.', ','))
.isPresent()
.get().isEqualTo(-1800);
}

@Test
void test_integer_negativeWithSpace_noCurrency()
{
assertThat(AmountParser.parse("- 200"))
assertThat(AmountParser.parse("- 200", '.', ','))
.isPresent()
.get().isEqualTo(-20000);
}

@Test
void test_integer_positive_currency()
{
assertThat(AmountParser.parse("12 €"))
assertThat(AmountParser.parse("12 €", '.', ','))
.isPresent()
.get().isEqualTo(1200);
}

@Test
void test_integer_negative_currency()
{
assertThat(AmountParser.parse("-18€"))
assertThat(AmountParser.parse("-18€", '.', ','))
.isPresent()
.get().isEqualTo(-1800);
}

@Test
void test_integer_positiveWithSign_noCurrency()
{
assertThat(AmountParser.parse("+12"))
assertThat(AmountParser.parse("+12", '.', ','))
.isPresent()
.get().isEqualTo(1200);
}

@Test
void test_integer_positiveWithSignWithSpace_noCurrency()
{
assertThat(AmountParser.parse("+ 12"))
assertThat(AmountParser.parse("+ 12", '.', ','))
.isPresent()
.get().isEqualTo(1200);
}

@Test
void test_thousandsDelimiter_integer()
{
assertThat(AmountParser.parse("1,234", '.', ','))
.isPresent()
.get().isEqualTo(123400);
}

@Test
void test_thousandsDelimiter_dot()
{
assertThat(AmountParser.parse("1,234.03", '.', ','))
.isPresent()
.get().isEqualTo(123403);
}

@Test
void test_thousandsDelimiter_withCurrency()
{
assertThat(AmountParser.parse("1,234.03 €", '.', ','))
.isPresent()
.get().isEqualTo(123403);
}

@Test
void test_thousandsDelimiter_negative()
{
assertThat(AmountParser.parse("-1,234.03 €", '.', ','))
.isPresent()
.get().isEqualTo(-123403);
}

@Test
void test_thousandsDelimiter_specialDelimiter()
{
assertThat(AmountParser.parse("-1.234,03 €", ',', '.'))
.isPresent()
.get().isEqualTo(-123403);
}

@Test
void test_thousandsDelimiter_bigNumber()
{
assertThat(AmountParser.parse("-1.234.567,03 €", ',', '.'))
.isPresent()
.get().isEqualTo(-123456703);
}
}

0 comments on commit 35daa09

Please sign in to comment.