Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix TryParseFeetInches when current locale uses ' as number separator #794

Closed
wants to merge 6 commits into from

Conversation

pgrawehr
Copy link
Contributor

My current locale (de-CH) uses ' (an apostrophe) as thousands separator. This broke the unit test for the TryParseFeetInches method, because the input string 1'1" is ambiguous. Therefore I now removed the separator as valid input in a feet-inches combination. It's pretty unlikely that someone will need to parse 1,345'21".

@codecov-commenter
Copy link

codecov-commenter commented May 26, 2020

Codecov Report

Merging #794 into master will increase coverage by 1.90%.
The diff coverage is 100.00%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #794      +/-   ##
==========================================
+ Coverage   78.60%   80.51%   +1.90%     
==========================================
  Files         280      280              
  Lines       41834    41850      +16     
==========================================
+ Hits        32884    33695     +811     
+ Misses       8950     8155     -795     
Impacted Files Coverage Δ
UnitsNet/CustomCode/Quantities/Length.extra.cs 86.95% <100.00%> (+0.43%) ⬆️
UnitsNet/CustomCode/QuantityParser.cs 97.05% <100.00%> (+0.18%) ⬆️
UnitsNet/QuantityFormatter.cs 94.44% <0.00%> (-2.11%) ⬇️
...tensions/GeneratedCode/NumberToAreaExtensions.g.cs 100.00% <0.00%> (ø)
...tensions/GeneratedCode/NumberToMassExtensions.g.cs 100.00% <0.00%> (ø)
...ensions/GeneratedCode/NumberToAngleExtensions.g.cs 100.00% <0.00%> (ø)
...ensions/GeneratedCode/NumberToForceExtensions.g.cs 100.00% <0.00%> (ø)
...ensions/GeneratedCode/NumberToLevelExtensions.g.cs 100.00% <0.00%> (ø)
...ensions/GeneratedCode/NumberToPowerExtensions.g.cs 100.00% <0.00%> (ø)
...ensions/GeneratedCode/NumberToRatioExtensions.g.cs 100.00% <0.00%> (ø)
... and 195 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 3b36fd9...310db24. Read the comment docs.

Copy link
Owner

@angularsen angularsen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very nice, looks good to me. Just a couple minor comments.

UnitsNet/CustomCode/Quantities/Length.extra.cs Outdated Show resolved Hide resolved
UnitsNet.Tests/QuantityIFormattableTests.cs Show resolved Hide resolved
@tmilnthorp
Copy link
Collaborator

I'm not so certain that just ignoring it is a good idea. Looks like we're missing a couple tests though - for your case as well as a number separated by a '

When the thousands separator is ' (i.e. de-CH language settings)
parsing 1'1" feet failed.
@pgrawehr
Copy link
Contributor Author

I'm not so certain that just ignoring it is a good idea. Looks like we're missing a couple tests though - for your case as well as a number separated by a '

What test cases are you thinking of? If the number is i.e. embedded in quotes, then I think it's ok to have parsing fail, as quotes are not part of a number (except in the case where the quote is one of the valid separators).

@tmilnthorp
Copy link
Collaborator

I added an example here: #799. I'm confused now though because it passes :)

@pgrawehr
Copy link
Contributor Author

@tmilnthorp : And I'm confused now because my updated test fails :-/

Output:

Error Message:
   Assert.Equal() Failure
           � (pos 1)
Expected: 2'012.12 øC
Actual:   2'012.12 øC
           � (pos 1)
  Stack Trace:
     at UnitsNet.Tests.QuantityIFormattableTests.FormatStringWorksWithSuppliedLocale() in C:\projects\unitsnet\UnitsNet.Tests\QuantityIFormattableTests.cs:line 90

The strings are exactly the same to me...

I'll check what's going on with your PR.

@angularsen
Copy link
Owner

angularsen commented May 28, 2020 via email

@tmilnthorp
Copy link
Collaborator

Oh man. There's the right single quotation mark U+2019 and an apostrophe U+0027.

Sometimes, I feel like I know nothing 😆

@angularsen
Copy link
Owner

angularsen commented May 28, 2020

To be fair, xUnit COULD have been nice enough to help identify this by providing the character values when there is a single character off.

@pgrawehr
Copy link
Contributor Author

$"{temperature}".ToString(myCulture)

The reason is: It's defined that way: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/expressions#interpolated-strings

The type of $"..." is string, unless you immediatelly assign it to FormattableString. So the type of the expression is derived from the left-hand-side of the assigment.


// This does not work. Looks like a compiler bug to me.
// string f2 = $"{t:g}".ToString(c);
// Assert.Equal("2'012.12 °C", f2.ToString(c)); // Actual value is formatted according to CurrentUiCulture.
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The commented code does not work, because these two statements are equivalent:

string f2 = $"{t:g}".ToString(c);
string f2 = t.ToString("g").ToString(c);

LINQPad sample

when CurrentUICulture is Norwegian and thousand separator is comma ,.

Temperature t = Temperature.FromDegreesCelsius(2012.1234);
CultureInfo c = new CultureInfo("de-CH", false);

FormattableString f = $"{t:g}";
string f2 = $"{t:g}".ToString(c);
string f3 = t.ToString("g").ToString(c);

var expected = "2" + c.NumberFormat.NumberGroupSeparator + "012" + c.NumberFormat.NumberDecimalSeparator + "12 °C";
(expected == f.ToString(c).Dump()).Dump();
(expected == f2.ToString(c).Dump()).Dump(); // Actual value is formatted according to CurrentUiCulture.
(expected == f3.ToString(c).Dump()).Dump(); // Actual value is formatted according to CurrentUiCulture.

Output:

2’012.12 °C
True
2,012.12 °C
False
2,012.12 °C
False

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove the commented code from this PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As you've seen

FormattableString f = $"{t:g}";
string result = f.ToString(c);

is not equivalent to

string result = $"{t:g}".ToString(c);

which is what confused me (as this would be the case for every other expression).

I'll remove it, since the problem has nothing to do with this lib, but is a (weird but documented) feature of the CLR.

@@ -80,7 +101,8 @@ public static bool TryParseFeetInches(string? str, out Length result, IFormatPro
str = str.Trim();

// This succeeds if only feet or inches are given, not both
if (TryParse(str, formatProvider, out result))
// Do not allow thousands separator here, since it may be equal to the unit abbreviation (').
if (TryParse(str, formatProvider, NumberStyles.Float, out result))
Copy link
Owner

@angularsen angularsen May 30, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As @tmilnthorp pointed out earlier, we should have unit tests that covers the new behavior for feet-inches. It should test what happens if you try to parse strings like these, with a culture that has apostrophe character as thousand separator. We could also test cultures with other thousand separators, like nb-NO Norwegian that has . as separator (instead of , in US English).

1'500' 4"
1'5002′−4″
1'500 ft 4 in
1'5002′ 4″

My intuition tells me we should get an exception when parsing these, because the thousand separator is no longer allowed and in the first case the feet symbol is even listed twice.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll do that, but I feel we should somehow merge @tmilnthorp s PR with this one, otherwise it gets confusing.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess we can wait for #799 to merge first to reuse the combinatorial parameter refactoring that is about to be added there.

Copy link
Owner

@angularsen angularsen Jun 1, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#799 was abandoned, please see #803 for supporting thousand separators in regex instead of not allowing them. I think that may be a better solution to this problem.

@stale
Copy link

stale bot commented Aug 1, 2020

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the wontfix label Aug 1, 2020
@stale stale bot closed this Aug 8, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants