@@ -14,7 +14,66 @@ namespace UnitsNet
14
14
public class QuantityFormatter
15
15
{
16
16
/// <summary>
17
- /// Formats the given quantity using the given format string and format provider.
17
+ /// The available UnitsNet custom format specifiers.
18
+ /// </summary>
19
+ private static readonly char [ ] UnitsNetFormatSpecifiers = { 'A' , 'a' , 'G' , 'g' , 'Q' , 'q' , 'S' , 's' , 'U' , 'u' , 'V' , 'v' } ;
20
+
21
+ /// <summary>
22
+ /// Formats a quantity using the given format string and format provider.
23
+ /// </summary>
24
+ /// <typeparam name="TUnitType">The quantity's unit type, for example <see cref="LengthUnit"/>.</typeparam>
25
+ /// <param name="quantity">The quantity to format.</param>
26
+ /// <param name="format">The format string.</param>
27
+ /// <remarks>
28
+ /// The valid format strings are as follows:
29
+ /// <list type="bullet">
30
+ /// <item>
31
+ /// <term>A standard numeric format string.</term>
32
+ /// <description>Any of the standard numeric format for <see cref="IQuantity.Value" /> except for "G" or "g".
33
+ /// "C" or "c", "E" or "e", "F" or "f", "N" or "n", "P" or "p", "R" or "r" are all accepted.
34
+ /// </description>
35
+ /// </item>
36
+ /// <item>
37
+ /// <term>"G" or "g".</term>
38
+ /// <description>The value with 2 significant digits after the radix followed by the unit abbreviation, such as "1.23 m".</description>
39
+ /// </item>
40
+ /// <item>
41
+ /// <term>"A" or "a".</term>
42
+ /// <description>The default unit abbreviation for <see cref="IQuantity{TUnitType}.Unit" />, such as "m".</description>
43
+ /// </item>
44
+ /// <item>
45
+ /// <term>"A0", "A1", ..., "An" or "a0", "a1", ..., "an".</term>
46
+ /// <description>The n-th unit abbreviation for <see cref="IQuantity{TUnitType}.Unit" />. "a0" is the same as "a".
47
+ /// A <see cref="FormatException"/> will be thrown if the requested abbreviation index does not exist.</description>
48
+ /// </item>
49
+ /// <item>
50
+ /// <term>"V" or "v".</term>
51
+ /// <description>The string representation of <see cref="IQuantity.Value" /> using the default ToString method.</description>
52
+ /// </item>
53
+ /// <item>
54
+ /// <term>"U" or "u".</term>
55
+ /// <description>The enum name of <see cref="IQuantity{TUnitType}.Unit" />, such as "Meter".</description>
56
+ /// </item>
57
+ /// <item>
58
+ /// <term>"Q" or "q".</term>
59
+ /// <description>The quantity name, such as "Length".</description>
60
+ /// </item>
61
+ /// <item>
62
+ /// <term>"S1", "S2", ..., "Sn" or "s1", "s2", ..., "sn".</term>
63
+ /// <description>The value with n significant digits after the radix followed by the unit abbreviation. For example,
64
+ /// "s4" would return "1.2345 m" if <see cref="IQuantity.Value" /> is 1.2345678. Trailing zeros are omitted.</description>
65
+ /// </item>
66
+ /// </list>
67
+ /// </remarks>
68
+ /// <returns>The string representation.</returns>
69
+ public static string Format < TUnitType > ( IQuantity < TUnitType > quantity , string format )
70
+ where TUnitType : Enum
71
+ {
72
+ return Format ( quantity , format , CultureInfo . CurrentUICulture ) ;
73
+ }
74
+
75
+ /// <summary>
76
+ /// Formats a quantity using the given format string and format provider.
18
77
/// </summary>
19
78
/// <typeparam name="TUnitType">The quantity's unit type, for example <see cref="LengthUnit"/>.</typeparam>
20
79
/// <param name="quantity">The quantity to format.</param>
@@ -23,57 +82,108 @@ public class QuantityFormatter
23
82
/// <see cref="CultureInfo.CurrentUICulture" /> if null.</param>
24
83
/// <remarks>
25
84
/// The valid format strings are as follows:
26
- /// "g": The value with 2 significant digits after the radix followed by the unit abbreviation, such as "1.23 m".
27
- /// "a": The default unit abbreviation for <see cref="IQuantity{TUnitType}.Unit" />, such as "m".
28
- /// "a0", "a1", ..., "aN": The Nth unit abbreviation for <see cref="IQuantity{TUnitType}.Unit" />. "a0" is the same as "a".
29
- /// A <see cref="FormatException"/> will be thrown if the requested abbreviation index does not exist.
30
- /// "v": String representation of <see cref="IQuantity.Value" />.
31
- /// "u": The enum name of <see cref="IQuantity{TUnitType}.Unit" />, such as "Meter".
32
- /// "q": The quantity name, such as "Length".
33
- /// "s1", "s2", ..., "sN": The value with N significant digits after the radix followed by the unit abbreviation. For example,
34
- /// "s4" would return "1.2345 m" if <see cref="IQuantity.Value" /> is 1.2345678. Trailing zeros are omitted.
85
+ /// <list type="bullet">
86
+ /// <item>
87
+ /// <term>A standard numeric format string.</term>
88
+ /// <description>Any of the standard numeric format for <see cref="IQuantity.Value" /> except for "G" or "g".
89
+ /// "C" or "c", "E" or "e", "F" or "f", "N" or "n", "P" or "p", "R" or "r" are all accepted.
90
+ /// </description>
91
+ /// </item>
92
+ /// <item>
93
+ /// <term>"G" or "g".</term>
94
+ /// <description>The value with 2 significant digits after the radix followed by the unit abbreviation, such as "1.23 m".</description>
95
+ /// </item>
96
+ /// <item>
97
+ /// <term>"A" or "a".</term>
98
+ /// <description>The default unit abbreviation for <see cref="IQuantity{TUnitType}.Unit" />, such as "m".</description>
99
+ /// </item>
100
+ /// <item>
101
+ /// <term>"A0", "A1", ..., "An" or "a0", "a1", ..., "an".</term>
102
+ /// <description>The n-th unit abbreviation for <see cref="IQuantity{TUnitType}.Unit" />. "a0" is the same as "a".
103
+ /// A <see cref="FormatException"/> will be thrown if the requested abbreviation index does not exist.</description>
104
+ /// </item>
105
+ /// <item>
106
+ /// <term>"V" or "v".</term>
107
+ /// <description>The string representation of <see cref="IQuantity.Value" /> using the default ToString method.</description>
108
+ /// </item>
109
+ /// <item>
110
+ /// <term>"U" or "u".</term>
111
+ /// <description>The enum name of <see cref="IQuantity{TUnitType}.Unit" />, such as "Meter".</description>
112
+ /// </item>
113
+ /// <item>
114
+ /// <term>"Q" or "q".</term>
115
+ /// <description>The quantity name, such as "Length".</description>
116
+ /// </item>
117
+ /// <item>
118
+ /// <term>"S1", "S2", ..., "Sn" or "s1", "s2", ..., "sn".</term>
119
+ /// <description>The value with n significant digits after the radix followed by the unit abbreviation. For example,
120
+ /// "s4" would return "1.2345 m" if <see cref="IQuantity.Value" /> is 1.2345678. Trailing zeros are omitted.</description>
121
+ /// </item>
122
+ /// </list>
35
123
/// </remarks>
36
124
/// <returns>The string representation.</returns>
37
125
public static string Format < TUnitType > ( IQuantity < TUnitType > quantity , string format , IFormatProvider ? formatProvider )
38
126
where TUnitType : Enum
39
127
{
40
- formatProvider = formatProvider ?? CultureInfo . CurrentUICulture ;
128
+ formatProvider ??= CultureInfo . CurrentUICulture ;
41
129
42
- var number = 0 ;
43
- var formatString = format ;
130
+ if ( string . IsNullOrWhiteSpace ( format ) )
131
+ format = "g" ;
44
132
45
- if ( string . IsNullOrEmpty ( formatString ) )
46
- formatString = "g" ;
133
+ char formatSpecifier = format [ 0 ] ;
47
134
48
- if ( formatString . StartsWith ( "a" ) || formatString . StartsWith ( "s" ) )
135
+ if ( UnitsNetFormatSpecifiers . Any ( unitsNetFormatSpecifier => unitsNetFormatSpecifier == formatSpecifier ) )
49
136
{
50
- if ( formatString . Length > 1 && ! int . TryParse ( formatString . Substring ( 1 ) , out number ) )
51
- throw new FormatException ( $ "The { format } format string is not supported.") ;
137
+ // UnitsNet custom format string
52
138
53
- formatString = formatString . Substring ( 0 , 1 ) ;
54
- }
139
+ int precisionSpecifier = 0 ;
55
140
56
- switch ( formatString )
57
- {
58
- case "g" :
59
- return ToStringWithSignificantDigitsAfterRadix ( quantity , formatProvider , 2 ) ;
60
- case "a" :
61
- var abbreviations = UnitAbbreviationsCache . Default . GetUnitAbbreviations ( quantity . Unit , formatProvider ) ;
141
+ switch ( formatSpecifier )
142
+ {
143
+ case 'A' :
144
+ case 'a' :
145
+ case 'S' :
146
+ case 's' :
147
+ if ( format . Length > 1 && ! int . TryParse ( format . Substring ( 1 ) , out precisionSpecifier ) )
148
+ throw new FormatException ( $ "The { format } format string is not supported.") ;
149
+ break ;
150
+ }
151
+
152
+ switch ( formatSpecifier )
153
+ {
154
+ case 'G' :
155
+ case 'g' :
156
+ return ToStringWithSignificantDigitsAfterRadix ( quantity , formatProvider , 2 ) ;
157
+ case 'A' :
158
+ case 'a' :
159
+ var abbreviations = UnitAbbreviationsCache . Default . GetUnitAbbreviations ( quantity . Unit , formatProvider ) ;
160
+
161
+ if ( precisionSpecifier >= abbreviations . Length )
162
+ throw new FormatException ( $ "The { format } format string is invalid because the abbreviation index does not exist.") ;
62
163
63
- if ( number >= abbreviations . Length )
64
- throw new FormatException ( $ "The { format } format string is invalid because the abbreviation index does not exist.") ;
164
+ return abbreviations [ precisionSpecifier ] ;
165
+ case 'V' :
166
+ case 'v' :
167
+ return quantity . Value . ToString ( formatProvider ) ;
168
+ case 'U' :
169
+ case 'u' :
170
+ return quantity . Unit . ToString ( ) ;
171
+ case 'Q' :
172
+ case 'q' :
173
+ return quantity . QuantityInfo . Name ;
174
+ case 'S' :
175
+ case 's' :
176
+ return ToStringWithSignificantDigitsAfterRadix ( quantity , formatProvider , precisionSpecifier ) ;
177
+ default :
178
+ throw new FormatException ( $ "The { format } format string is not supported.") ;
179
+ }
180
+ }
181
+ else
182
+ {
183
+ // Anything else is a standard numeric format string with default unit abbreviation postfix.
65
184
66
- return abbreviations [ number ] ;
67
- case "v" :
68
- return quantity . Value . ToString ( formatProvider ) ;
69
- case "u" :
70
- return quantity . Unit . ToString ( ) ;
71
- case "q" :
72
- return quantity . QuantityInfo . Name ;
73
- case "s" :
74
- return ToStringWithSignificantDigitsAfterRadix ( quantity , formatProvider , number ) ;
75
- default :
76
- throw new FormatException ( $ "The { format } format string is not supported.") ;
185
+ var abbreviations = UnitAbbreviationsCache . Default . GetUnitAbbreviations ( quantity . Unit , formatProvider ) ;
186
+ return string . Format ( formatProvider , $ "{{0:{ format } }} {{1}}", quantity . Value , abbreviations . First ( ) ) ;
77
187
}
78
188
}
79
189
0 commit comments