Don't override .NET format string G - #1206
Conversation
tmilnthorp
commented
Feb 17, 2023
Fun times. Standard .NET formatting for |
angularsen
commented
Feb 17, 2023
Awesome! |
tmilnthorp
commented
Feb 22, 2023
@angularsen alright. I made everything match the runtime default (which is "G" by the way, not "g"). Obviously not an API breaking change, but it is a behavior change. Perhaps for the better. Merge now or is this a v6 thing? |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
| @@ -119,7 +119,7 @@ private static string FormatUntrimmed<TUnitType>(IQuantity<TUnitType> quantity, | |||
| formatProvider ??= CultureInfo.CurrentCulture; | |||
| if (string.IsNullOrWhiteSpace(format)) | |||
There was a problem hiding this comment.
This is out of scope for this PR, but the IsNullOrWhitespace seems non-standard.
The .NET number formatting source code seems to require exact matches on standard formats g, g2, x8 etc.
If there is no exact match on standard formats, such as trailing whitespace, it falls back to custom formatting, where they substitute placeholders like 0 and # for numbers, or yyyy for dates.
UnitsNet has defined some "standard" formats, but I'm wondering if we should split these up into standard formats and custom formats too. Standard formats ("g", "f") would require exact match, while custom formats ("q", "u") would allow some interpolation of placeholders.
CultureInfo.CurrentCulture=CultureInfo.GetCultureInfo("en");varl=Length.FromFeet(1000.23456789);voidPrint(stringfmt)=>l.ToString(fmt).Dump(fmt);// ## Standard formats for UnitsNet (requires exact match)Print("g");// 1,000.23 ft (rounds to 2 decimals, .NET standard numeric format would render 1.23456789)// Standard formats using the corresponding .NET standard numeric format for the double/decimal valuePrint("c");// ¤1,000.23 ftPrint("e");// 1.000235e+003 ftPrint("f");// 1000.235 ftPrint("n");// 1,000.235 ftPrint("p");// 100,023.457% ftPrint("r");// 1000.23456789 ftPrint("#.0");// 1000.2 ftPrint("00000.0");// 01000.2 ft// FormatException, only for integer types:// Print("x"); // Print("d");// ## Custom formats for UnitsNet (could allow interpolation)Print("a");// ft Print("a1");// ' Print("q");// LengthPrint("u");// Foot // Example of custom format interpolations that do not currently work:Print("u (a)");// ❌ "Foot", but expected "Foot (ft)"Print("q,u");// ❌ "Length", but expected "Length,Foot"I'm not sure I see a big use case for custom formats in UnitsNet though, beyond sticking to .NET conventions.
Thoughts?
| /// <term>A standard numeric format string.</term> | ||
| /// <description>Any of the standard numeric format for <see cref="IQuantity.Value" />, except for "G" or "g", which have a special implementation. | ||
| /// "C" or "c", "E" or "e", "F" or "f", "N" or "n", "P" or "p", "R" or "r" are all accepted. | ||
| /// <description>Any of the standard numeric format for <see cref="IQuantity.Value" />. |
There was a problem hiding this comment.
Maybe mention that integral standard formats won't work, such as d/D and x/X.
Also link to the standard formats:
https://learn.microsoft.com/en-us/dotnet/standard/base-types/standard-numeric-format-strings#standard-format-specifiers
Uh oh!
There was an error while loading. Please reload this page.
tmilnthorp
commented
Feb 26, 2023
@angularsen updated per your suggestions. I think we should also remove
These don't really add anything you can't do via the Also maybe |
Yes I'm thinking the same for Q/U. Remove it. You don't obtain "Seconds" from TimeSpan.ToString() either. It's an odd thing to do and unit/quantity name is available elsewhere. Regarding P (percentage, numeric standard format), I think we should not support neither C (currency) nor P (percentage). They don't make sense. So I think we should choose the subset of standard formats we support, and document them. |
tmilnthorp
commented
Feb 27, 2023
Sorry, I meant I'll remove Q/U/V. Regarding P, or any other default format string that's invalid for us. Should we just blindly allow strings of out say |
angularsen
commented
Mar 4, 2023
FormatException 👍
It would be more consistent, but then you can't control the number formatting, for example to 2 digits after radix. I think abbreviations are more useful as a custom format for string interpolation: varx=$"{myLength.Value:f2}{myLength:a0}";// 5 ftvary=$"{myLength.Value:f2}{myLength:a1}";// 5 'I think this is how it would look like: // Standard formats with .NET standard/custom numeric format + default unit abbreviationPrint("e");// 1.000235e+003 ftPrint("e2");// 3.14e+000 ftPrint("f");// 1000.235 ftPrint("f1");// 1000.2 ftPrint("n");// 1,000.235 ftPrint("n2");// 1,000.23 ftPrint("r");// 1000.23456789 ftPrint("#.0");// 1000.2 ftPrint("00000.0");// 01000.2 ft// Custom formats -- For string interpolation.Print("a");// ft Print("a1");// '// FormatException thrown by dotnet, only for integer types:// Print("x"); // Print("d");// FormatException thrown by us, no longer supportedPrint("c");// ¤1,000.23 ft Print("p");// 100,023.457% ft Print("q");// Length Print("u");// Foot Print("v");// 1000.23456789 |
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. |
@lipchev It's been ages, but isn't this more or less ready to go? Can you update the PR description with a summary of the changes? |
lipchev
commented
Dec 9, 2024
@angularsen do we still want this? can I include it in my v6 proposal? |
angularsen
commented
Dec 9, 2024
Yeah I belive this is still useful. What do you mean by including it in your v6 proposal? |
lipchev
commented
Dec 10, 2024
Don't worry, I'll split it and it's still going to be...godzilla 🐲 PS Lol, Is that a dragon emoji? I don't think you should be allowed to go around, claiming you're old.. 🤣 |
angularsen
commented
Dec 10, 2024
Lol 😆 |
- [x] `QuantityFormatter` defaults to the "G" format for null or empty string - [x] `QuantityFormatter` no longer supports the `U`/`V`/`Q` formats (an exception is thrown) - [x] `QuantityFormatter` explicitly throws for the `Cx`/`Px` formats - [x] `QuantityFormatter` shouldn't throw for something like "P1: #.00" (instead it should output something like "P1: 12.34 mg") - [x] `QuantityFormatter` unless explicitly given an incorrect `Ax` specifier, the `QuantityFormatter` uses the "default unit abbreviation" - which maybe `string.Empty` (if none are defined for a given unit) Fixes#1183 Duplicate of #1206 CC @tmilnthorp --------- Co-authored-by: Andreas Gullberg Larsen <andreas.larsen84@gmail.com>
angularsen
commented
Dec 15, 2024
Merged in #1450 |
Fixes#1183