Darkatek7
Darkatek7

Reputation: 53

How to get any currency format to be converted into "de-de" in C#

I get the currency values from a website... they could be in any currency format as the site is various in multiple countries.

what i currently have:

var actualPriceString = actualPriceElement.Text;
var actualPriceDe = Convert.ToDecimal(actualPriceString).ToString("C0", CultureInfo.GetCultureInfo("de-de"));
var maxPriceDe = Convert.ToDecimal(product.Max_Price).ToString("C0", CultureInfo.GetCultureInfo("de-de"));

if (Convert.ToDecimal(actualPriceDe) <= Convert.ToDecimal(maxPriceDe))
  run = await ClickElement(_config.site.add_to_cart, driver);

which just gives me errors or not what I wat at all.

I get errors when convert to decimal:

exception.Message = "Input string was not in a correct format."

The currency formats can look like those for example: 3.399,00 or 3,399.00

I also tried finding results online but all I get is from one currency Format to any other...

Thanks for your help!

Upvotes: 2

Views: 317

Answers (1)

Dmitrii Bychenko
Dmitrii Bychenko

Reputation: 186803

You can't solve the problem in general case, however, we can fight for some restricted cases:

  1. We assume that negative value uses simple leading -: -123.456,78
  2. We assume that we have no more than 2 positions for cents
  3. We assume that decimal and group separators are not mixed: 12,45,67 == 123456
  4. We ignore currency symbols, all sums are assumed to be in euro

Code:

public static decimal MyConversion(string value) {
  if (string.IsNullOrWhiteSpace(value))
    throw new FormatException("Not a valid currency");

  value = string.Concat(value
    .Reverse()
    .SkipWhile(c => !char.IsDigit(c))
    .Reverse()
    .SkipWhile(c => !char.IsDigit(c) && c != '-'));

  HashSet<char> separators = new HashSet<char>();
  int suggestSeparatorIndex = -1;

  StringBuilder sb = new StringBuilder(value.Length);

  for (int i = 0; i < value.Length; ++i) {
    char c = value[i];

    if (char.IsDigit(c))
      sb.Append(c);
    else if (c == '-' && i == 0)
      sb.Append(c);
    else if (!char.IsWhiteSpace(c)) 
      if (separators.Add(c))
        suggestSeparatorIndex = sb.Length;
      else
        suggestSeparatorIndex = -1;
  }

  if (suggestSeparatorIndex >= 0 && suggestSeparatorIndex >= sb.Length - 2)
    sb.Insert(suggestSeparatorIndex, '.');

  return decimal.Parse(sb.ToString(), CultureInfo.InvariantCulture) + 0.00m;
}

Demo:

  string[] tests = new string[] {
    "3.399,00", 
    "3,399.00",
    "123,345,789.0",
    "123.1",
    "12.23.45", // here '.' is a group separator
    "123",
    "456 $ 89 cents", // we ignore $ here, no currency exchange will be done
    "$56.89",
    "123=35 (euro)",
    "56 Евро 89 центов", // Russian, stands for 56 Euro 89 cents
  };

  // Deutschland Kultur (German Culture settings)
  CultureInfo.CurrentCulture = CultureInfo.GetCultureInfo("de-De");

  string report = string.Join(Environment.NewLine, tests
    .Select(test => $"{test,25} => {MyConversion(test)}"));

  Console.Write(report);

Outcome:

             3.399,00 => 3399,00
             3,399.00 => 3399,00
        123,345,789.0 => 123345789,00
                123.1 => 123,10
             12.23.45 => 122345,00
                  123 => 123,00
       456 $ 89 cents => 456,89
               $56.89 => 56,89
        123=35 (euro) => 123,35
    56 Евро 89 центов => 56,89

Upvotes: 1

Related Questions