2

This is a .NET Core 3.1 console app I've created to demonstrate an issue in a larger class library. I run it on a Windows 10 box build 18362

static void Main(string[] args)
{
    string cur = "19,99 €";
    CultureInfo ci = new CultureInfo("de-DE");
    decimal num = decimal.Parse(cur, NumberStyles.Any, ci.NumberFormat);
}

Why does the line decimal num = decimal.Parse(cur, NumberStyles.Any, ci.NumberFormat); throw

System.FormatException: 'Input string was not in a correct format.'

EDIT

I've added the line

Debug.WriteLine(JsonConvert.SerializeObject(ci.NumberFormat, Formatting.Indented))

The output is

{
  "CurrencyDecimalDigits": 2,
  "CurrencyDecimalSeparator": ",",
  "IsReadOnly": false,
  "CurrencyGroupSizes": [
    3
  ],
  "NumberGroupSizes": [
    3
  ],
  "PercentGroupSizes": [
    3
  ],
  "CurrencyGroupSeparator": ".",
  "CurrencySymbol": "€",
  "NaNSymbol": "NaN",
  "CurrencyNegativePattern": 8,
  "NumberNegativePattern": 1,
  "PercentPositivePattern": 0,
  "PercentNegativePattern": 0,
  "NegativeInfinitySymbol": "-∞",
  "NegativeSign": "-",
  "NumberDecimalDigits": 2,
  "NumberDecimalSeparator": ",",
  "NumberGroupSeparator": ".",
  "CurrencyPositivePattern": 3,
  "PositiveInfinitySymbol": "∞",
  "PositiveSign": "+",
  "PercentDecimalDigits": 2,
  "PercentDecimalSeparator": ",",
  "PercentGroupSeparator": ".",
  "PercentSymbol": "%",
  "PerMilleSymbol": "‰",
  "NativeDigits": [
    "0",
    "1",
    "2",
    "3",
    "4",
    "5",
    "6",
    "7",
    "8",
    "9"
  ],
  "DigitSubstitution": 1
}

EDIT 2 This code runs without exception when the German currency value is typed directly. However when the value is copied from the input stream that provides German currency values it throws the exception. I've tried looping through

foreach (char c in cur)
{
    System.Diagnostics.Debug.WriteLine(Char.GetNumericValue(c));
}

with a breakpoint in the loop but c is always one of 19,99 €

How do I find what characters are causing

System.FormatException

to throw?

EDIT 3 The input stream that contains the German currency with a hidden character comes from the Microsoft Store,

StoreProduct.Price.FormattedPrice

The string "19,99 €" has an appended Unicode Character 160 Non-breaking space. By stripping this out as per https://stackoverflow.com/a/18018166 with

cur = Regex.Replace(cur, @"[^\u001F-\u007F]", string.Empty);

The problem goes away.

Vague
  • 2,198
  • 3
  • 18
  • 46
  • 3
    Can you provide code that *actually fail*? (Code shown in the post works perfectly fine, and aligns with standard https://stackoverflow.com/questions/36001525/parse-value-with-currency-symbol answer). – Alexei Levenkov Feb 10 '20 at 06:02
  • This is a Net Standard console app. Fails on decimal num = decimal.Parse(cur, NumberStyles.Any, ci.NumberFormat); I created this console app to demonstrate an issue that arises in a larger app that recieves German currency values as input so I can't take the currency symbol out. – Vague Feb 10 '20 at 06:06
  • 1
    @Vague Not on the ones I have access to - see [.net fiddle](https://dotnetfiddle.net/QjIKFg) – Sir Rufo Feb 10 '20 at 06:12
  • 2
    Consider to [edit] post to provide such information - it's is hard to see that "This is a Net Standard console app" (whatever you mean there as .Net standard only applicable to a library, exe targets either on of the Core versions of one of full Framework versions)... Also there is non-zero chance that you run code on Linux... Showing result of `Console.WriteLine((123.45m) .ToString("c", new CultureInfo("de-de")` may help a bit to... – Alexei Levenkov Feb 10 '20 at 06:13
  • 1
    If this isn't working for you, I'd be interested to see what the contents of `ci.NumberFormat` is on your machine. Especially regarding its `CurrencySymbol`, `CurrencyDecimalSeparator`, and `CurrencyGroupSeparator` properties. (`€`, `,`, and `.` respectively on my machine). – ProgrammingLlama Feb 10 '20 at 06:15
  • 1
    I've put [this code](https://rextester.com/EWMTI97574) together demonstrating the code working and the settings of `ci.NumberFormat`. Can you compare it to your own? – ProgrammingLlama Feb 10 '20 at 06:20
  • The serialized output shows CurrencySymbol ?. However when I break over CI CurrencySymbol is € – Vague Feb 10 '20 at 06:29
  • I've reopened your question since that doesn't seem to be an appropriate duplicate for your question, although it will take a better mind than mine to get to the bottom of this! :) – ProgrammingLlama Feb 10 '20 at 06:31
  • 1
    @Vague When writing to console the output will be affected by the console font. Write the json result to a file (in UTF-8 encoding) and post it – Sir Rufo Feb 10 '20 at 06:33
  • Thanks @SirRufo I've edited my question to show output to the Output window which correctly shows "CurrencySymbol": "€" – Vague Feb 10 '20 at 06:35
  • 1
    @Vague And I edited your question again to format the json. – Sir Rufo Feb 10 '20 at 06:37
  • 1
    There something totally different going on... All values in culture looks correct (in particular `CurrencyPositivePattern = 3` in addition to one mentioned by @John)... Code should work... I don't have any reasonable idea why... You may try `Console.WriteLine(decimal.Parse((123.45m) .ToString("c", new CultureInfo("de-de")), NumberStyles.Any, new CultureInfo("de-DE").NumberFormat));` to see if roundtrip parsing works... – Alexei Levenkov Feb 10 '20 at 06:41
  • @AlexeiLevenkov Debug.WriteLine((123.45m).ToString("c", new CultureInfo("de-DE"))); outputs 123,45 € – Vague Feb 10 '20 at 06:45
  • @AlexeiLevenkov (decimal.Parse((123.45m).ToString("c", new CultureInfo("de-de")), NumberStyles.Any, new CultureInfo("de-DE").NumberFormat)); outputs 123.45 – Vague Feb 10 '20 at 06:46
  • 1
    Are you 1000% sure the code you posted in the question is the one that fails? I don't see how parsing `123,45 €` works and `19,99 €` fails... Any chance that value of `cur` actually different on your machine (like copy-paste cleaned up some rtl-mark or something like that - check if length of the string matches...) ... – Alexei Levenkov Feb 10 '20 at 06:50
  • @AlexeiLevenkov abolutely $1000%. It fails in the demo just as it does in the main class library. Also cur.Length = 7 – Vague Feb 10 '20 at 06:54
  • @AlexeiLevenkov I copy and pasted 123,45 € into my code and it didn't fail. What's happening here? – Vague Feb 10 '20 at 06:56
  • @AlexeiLevenkov I then copy and pasted 19,99 € from this post back into my code and it didn't fail. I assume there must be junk buried in the input? – Vague Feb 10 '20 at 06:58
  • 4
    `Console.Write(string.Join(",", "19,99 €".Select(x => (int)x)))` should produce "49,57,44,57,57,32,8364". I bet someone gave you some other string that just looks the same and probably normalized on copy-paste... There are plenty of other digits in Unicode for example... – Alexei Levenkov Feb 10 '20 at 06:59
  • 2
    @AlexeiLevenkov I've had a look at other values that come in on this stream. It looks like all the German currency values coming in have hidden rubbish in them. Thanks for your help in getting to the bottom of it. – Vague Feb 10 '20 at 07:22

0 Answers0