One common task which always has me reaching for MSDN is working out how to format numbers, dates and times as strings. There are two ways of formatting in .NET: you can call ToString directly on the item you wish to format, passing in just a format string or you can use composite formatting with a call to String.Format to format more than one item at a time, or mix data and other text. In either case you can usually specify an IFormatProvider (such as CultureInfo) to help with internationalization. Many other methods in the .NET Framework also work with composite format strings, such as Console.WriteLine and StringBuilder.AppendFormat.
Composite format strings consist of normal text and format items containing an index and optionally an alignment and a format string. Figure 1 shows a sample of using composite format string, with each element labeled.
Figure 1. The anatomy of a call to String.Format
When the alignment isn't specified you omit the comma; when the format string isn't specified you omit the colon. Every format item must have an index as this says which of the following arguments to format. Arguments can be used any number of times, and in any order. In general, the alignment is used to specify a minimum width , if this is negative, the result is padded with spaces to the right; if it's positive, the result is padded with spaces to the left. The effect of the format string depends on the type of item being formatted. To include a brace as normal text in a composite format string (instead of it indicating the beginning or end of a format item), just double it. For example, the result of String.Format("{{0}}") is "{0}".
Numeric Format Strings
Numbers can be formatted in two ways: with standard or custom format strings. The standard ones allow some flexibility in terms of the precision and style, but the custom ones can be used for very specific formats.
Standard Numeric Format Strings
Standard numeric format strings all take the form of a single letter (the format specifier) and then optionally one or two digits (the precision). For example, a format string of N5 has N as the format specifier and 5 as the precision. The exact meaning of the precision depends on the format specifier, as described in table 2. If no precision is specified a suitable default is used based on the current IFormatProvider.
Format |
Description |
Precision |
Examples (with US English IFormatProvider) |
C or c |
Currency , exact format is specified by NumberFormatInfo |
Number of decimal places |
123.4567, "c" => "$123.46" 123.4567, "c3" => "$123.457" |
D or d |
Decimal (integer types only) |
Minimum number of digits |
123, "d5" => "00123" 123, "d2" => "123" |
E or e |
Scientific - used to express very large or small numbers in exponential format. |
Number of digits after the decimal point |
123456, "e2" => "1.23e+005" 123456, "E4" => "1.2345E+005" |
F or f |
f Fixed point |
Number of decimal places |
123.456, "f2" => "123.46" 123.4, "f3" => "123.400" |
G or g |
g General,chooses fixed or scientific notation based on number type and precision |
Depends on exact format used (see http://msdn.microsoft.com/en-us/library/dwhawy9k.aspx for details) |
123.4, "g2" => "1.2e+02" 123.4, "g6" => "123.4" 123.400m, "g" => "123.400" |
N or n |
Number,decimal form including thousands indicators (e.g. commas) |
Number of decimal places |
1234.567, "n2" => "1,234.57" |
P or p |
Percentage,number is multiplied by 100 and percentage sign is applied |
Number of decimal places |
0.1234, "p1" => "12.3 %" |
R or r |
Round-trip,if you later parse the result, you're guaranteed to get the original number. |
Ignored |
0.12345, "r" => 0.12345 |
X or x |
Hexadecimal (integer types only). The case of the result is the same as the case of the format specifier. |
Minimum number of digits |
123, "x" => "7b" 123, "X4" => "007B" |
Table 2. Standard numeric format strings
Custom Numeric Format Strings
To format numbers in a custom fashion, you provide a pattern to the formatter, consisting of format specifiers as shown in table 3.
Format Specifier |
Name |
Description |
0 |
Zero placeholder |
Always formatted as 0 or a digit from the original number |
# |
Decimal placeholder |
Formatted as a digit when it's a significant digit in the number, or omitted otherwise |
. |
Decimal point |
Formatted as the decimal point for the current IFormatProvider |
, |
Thousands separator and number scaling specifier |
When used between digit or zero placeholders, formatted as the group separator for the current IFormatProvider. When it's used directly before a decimal point (or an implicit decimal point) each comma effectively means "divide by a thousand". |
% |
Percentage placeholder |
Formatted as the percent symbol for the current IFormatProvider, and also multiplies the number by 100 |
"(\u2030) |
Per mille placeholder |
Similar to the percentage placeholder, but the number is multiplied by 1000 instead of 100, and the per mille symbol for the culture is used instead of the percent symbol. |
E0, e0, E+0, e+0, E-0, or e-0 |
Scientific notation |
Formats the number with scientific (exponential) notation. The number of 0s indicates the minimum number of digits to use when expressing the exponent. For E+0 and e+0, the exponent's sign is always expressed; otherwise it's only expressed for negative exponents. |
" or ' |
Quoting for literals |
Text between quotes is formatted exactly as it appears in the format string (i.e. it's not interpreted as a format pattern) |
; |
Section separator |
A format string can consist of up to three sections, separated by semi-colons. If only a single section is present, it is used for all numbers. If two sections are present, the first is used for positive numbers and zero; the second is used for negative numbers. If three sections are present, they are used for positive, negative and zero numbers respectively. |
\c |
Single-character escape |
Escapes a single character, i.e. the character c is displayed verbatim |
Table 3. Custom numeric format specifiers
Table 4 shows examples of custom numeric format strings, when formatted with a US English format provider.
Number |
Format String |
Output |
Notes |
123 |
####.00# |
123.00 |
0 forces a digit; # doesn't |
12345.6789 |
####.00# |
12345.679 |
Value is rounded to 3 decimal places |
1234 |
0,0.# |
1,234 |
Decimal point is omitted when not required |
1234 |
0,.#### |
1.234 |
Value has been divided by 1000 |
0.35 |
0.00% |
35.00% |
Value has been multiplied by 100 |
0.0234 |
0.0\u2030 |
23.4 |
|
0.1234 |
0.00E0 |
1.23E-1 |
Exponent specified with single digit |
1234 |
0.00e00 |
1.23e03 |
Exponent is specified with two digits, but sign is omitted |
1234 |
##'text0'### |
1text0234 |
The text0 part is not parsed as a format pattern |
12.34 |
0.0;000.00; 'zero' |
12.3 |
First section is used |
-12.34 |
0.0;000.00; 'zero' |
012.34 |
Second section is used |
0 |
0.0;000.00; 'zero' |
zero |
Third section is used |
Table 4. Sample custom numeric format strings and their results
Date and Time Format Strings
Dates and times tend to have more cultural sensitivity than numbers,the ordering of years, months and days in dates varies between cultures, as do the names of months and so forth. As with numbers, .NET allows both standard and custom format strings for dates and times.
Standard Date and Time Format Strings
Standard date and time format strings are always a single character. Any format string which is longer than that (including whitespace) is interpreted as a custom format string. The roundtrip (o or O), RFC1123 (r or R), sortable (s) and universal sortable (u) format specifiers are culturally invariant,in other words, they will produce the same output whichever IFormatProvider is used. Table 5 lists all of the standard date and time format specifiers.
Format Specifier |
Description |
Example (US English) |
d |
Short date pattern |
5/30/2008 |
D |
Long date pattern |
Friday, May 30, 2008 |
f |
Full date/time pattern (short time) |
Friday, May 30, 2008 8:40 PM |
F |
Full date/time pattern (long time) |
Friday, May 30, 2008 8:40:36 PM |
g |
General date/time pattern (short time) |
5/30/2008 8:40 PM |
G |
General date/time pattern (long time) |
5/30/2008 8:40:36 PM |
M or m |
Month day pattern |
May 30 |
O or o |
Round-trip pattern |
2008-05-30T20:40:36.8460000+01:00 |
R or r |
RFC1123 pattern (Assumes UTC: caller must convert.) |
Fri, 30 May 2008 19:40:36 GMT |
s |
Sortable date pattern (ISO 8601 compliant) |
2008-05-30T20:40:36 |
t |
Short time pattern |
8:40 PM |
T |
Long time pattern |
8:40:36 PM |
u |
Universal sortable date pattern (Assumes UTC: caller must convert.) |
2008-05-30 19:40:36Z |
U |
Universal full date/time pattern (Format automatically converts to UTC.) |
Friday, May 30, 2008 7:40:36 PM |
Y or y |
Year month pattern |
May, 2008 |
Table 5. Standard date and time format specifiers
Custom Date and Time Format Strings
As with numbers, custom date and time format strings form patterns which are used to build up the result. Many of the format specifiers act differently depending on the number of times they're repeated. For example, "d" is used to indicate the day,for a date falling on a Friday and the 5th day of the month, "d" (in a custom format string) would produce "5", "dd" would produce "05", "ddd" would produce "Fri" and "dddd" would produce "Friday" (in US English,other cultures will vary). Table 6 shows each of the custom date and time format specifiers, describing how their meanings change depending on repetition.
Format Specifier |
Meaning |
Notes and variance by repetition |
d, dd, ddd, dddd |
Day |
d 1-31
dd 01-31
ddd Abbreviated day name (e.g. Fri)
dddd Full day name (e.g. Friday)
|
f, ff ... fffffff |
Fractions of a second |
f Tenths of a second
ff Hundredths of a second (etc)
The specified precision is always used, with
insignificant zeroes included if necessary
|
F, FF ... FFFFFFF |
Fractions of a second |
Same as f ... fffffff except insignificant zeroes are omitted |
g |
Period or era |
For example, "A.D." |
h, hh |
Hour in 12 hour format |
h 1-12
hh 01-12
|
H, HH |
Hour in 24 hour format |
H 0-23
HH 00-23
|
K |
Time zone offset |
For example, +01:00; outputs Z for UTC values. |
m, mm |
Minute |
m 0-59
mm 00-59
|
M ... MMMM |
Month |
M 1-12
MM 01-12
MMM Abbreviated month name (e.g. Jan)
MMMM Full day name (e.g. January)
|
s, ss |
Seconds |
s 0-59
ss 00-59
|
t, tt |
AM/PM designator |
t First character only (e.g. "A" or "P")
tt Full designator (e.g. "AM" or "PM")
|
y ... yyyyy |
Year |
y 0-99 (least significant two digits are used)
yy 00-99 (least significant two digits are used)
yyy 000-9999 (three or four digits as necessary)
yyyy 0000-9999
yyyyy 00000-99999
|
z ... zzz |
Offset from UTC (of local operating system) |
z -12 to +13, single or double digit
zz -12 to +13, always double digit (e.g. +05)
zzz -12:00 to +13:00, hours and minutes
|
: |
Time separator |
Culture-specific symbol used to separate hours from minutes, etc. |
/ |
Date separator |
Culture-specific symbol used to separate months from days, etc. |
' |
Quoting for literals |
Text between two apostrophes is displayed verbatim. |
%c |
Single custom format specifier |
Uses c as a custom format specifier; used to force a pattern to be interpreted as a custom instead of a standard format specifier. |
\c |
Single-character escape |
Escapes a single character, i.e. the character c is displayed verbatim. |
Table 6. Custom date and time format specifiers
Typically only years within the range 1-9999 can be represented, but there are some exceptions due to cultural variations. See http://msdn.microsoft.com/en-us/library/8kb3ddd4.aspx for more details on this and all of the formatting topics.
Table 7 shows examples of custom date and time format strings, when formatted with a US English format provider. (The date and time in question is the same one used to demonstrate the standard format strings.)
Format String |
Output |
Notes |
yyyy/MM/dd-T-HH:mm:ss.fff |
2008/05/30T20:40:36.846 |
T is quoted for clarity only-T is not a format specifier, so would have been output anyway. |
d MMMM yy h:mm tt |
30 May 08 8:40 PM |
12 hour clock, single digit used |
HH:mm:sszzz |
20:40:36+01:00 |
24 hour clock, always two digits |
yyyy g |
2008 A.D. |
Rarely used, era is usually implicit |
yyyyMMddHHmmssfff |
20080530204036846 |
Not very readable, but easily sortable,handy for log filenames. Consider using UTC though. |
Table 7. Sample custom date and time format strings and their results
{{ parent.title || parent.header.title}}
{{ parent.tldr }}
{{ parent.linkDescription }}
{{ parent.urlSource.name }}