-
Notifications
You must be signed in to change notification settings - Fork 396
Fix TryParseFeetInches when current locale uses ' as number separator #794
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
Changes from all commits
b77e05b
c571add
4de3c57
54a8df1
0d24b46
310db24
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -65,6 +65,36 @@ public void SFormatEqualsSignificantDigits(string sFormatString, string expected | |
Assert.Equal(expected, length.ToString(sFormatString, NumberFormatInfo.InvariantInfo)); | ||
} | ||
|
||
/// <summary> | ||
/// This verifies that the culture is correctly considered when formatting objects with an explicit culture. | ||
/// </summary> | ||
[Fact] | ||
public void FormattingUsesSuppliedLocale() | ||
{ | ||
Temperature t = Temperature.FromDegreesCelsius(2012.1234); | ||
CultureInfo c = new CultureInfo("de-CH", false); | ||
string formatted = string.Format(c, "{0:g}", t); | ||
// Let's be very explicit here | ||
Assert.Equal("2" + c.NumberFormat.NumberGroupSeparator + "012" + c.NumberFormat.NumberDecimalSeparator + "12 °C", formatted); | ||
} | ||
|
||
/// <summary> | ||
/// This verifies that the culture is correctly considered when using <see cref="FormattableString.ToString(IFormatProvider)"/> | ||
/// </summary> | ||
[Fact] | ||
public void FormatStringWorksWithSuppliedLocale() | ||
{ | ||
Temperature t = Temperature.FromDegreesCelsius(2012.1234); | ||
CultureInfo c = new CultureInfo("de-CH", false); | ||
|
||
FormattableString f = $"{t:g}"; | ||
Assert.Equal("2" + c.NumberFormat.NumberGroupSeparator + "012" + c.NumberFormat.NumberDecimalSeparator + "12 °C", f.ToString(c)); | ||
angularsen marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
// 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. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 samplewhen 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:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Remove the commented code from this PR. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As you've seen
is not equivalent to
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. |
||
} | ||
|
||
[Fact] | ||
public void UFormatEqualsUnitToString() | ||
{ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -59,6 +59,27 @@ public static Length ParseFeetInches([NotNull] string str, IFormatProvider? form | |
return result; | ||
} | ||
|
||
/// <summary> | ||
/// Try to parse a string with one or two quantities of the format "<quantity> <unit>". | ||
/// </summary> | ||
/// <param name="str">String to parse. Typically in the form: {number} {unit}</param> | ||
/// <param name="provider">Format to use when parsing number and unit. Defaults to <see cref="CultureInfo.CurrentUICulture" /> if null.</param> | ||
/// <param name="allowedNumberStyles">Allowed number styles</param> | ||
/// <param name="result">Resulting unit quantity if successful.</param> | ||
/// <returns>True if successful, otherwise false.</returns> | ||
/// <example> | ||
/// Length.Parse("5.5 m", new CultureInfo("en-US")); | ||
/// </example> | ||
private static bool TryParse(string? str, IFormatProvider? provider, NumberStyles allowedNumberStyles, out Length result) | ||
{ | ||
return QuantityParser.Default.TryParse<Length, LengthUnit>( | ||
str, | ||
provider, | ||
From, | ||
allowedNumberStyles, | ||
out result); | ||
} | ||
|
||
/// <summary> | ||
/// Special parsing of feet/inches strings, commonly used. | ||
/// 2 feet 4 inches is sometimes denoted as 2′−4″, 2′ 4″, 2′4″, 2 ft 4 in. | ||
|
@@ -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)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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
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. There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
return true; | ||
|
||
var quantityParser = QuantityParser.Default; | ||
|
Uh oh!
There was an error while loading. Please reload this page.