Previous Section  < Day Day Up >  Next Section

5.6. Formatting Numeric and DateTime Values

The String.Format method is the primary means of formatting date and numeric data for display. It accepts a string composed of text and embedded format items followed by one or more data arguments. Each format item references a data argument and specifies how it is to be formatted. The CLR creates the output string by converting each data value to a string (using ToString), formatting it according to its corresponding format item, and then replacing the format item with the formatted data value. Here is a simple example:

String s= String.Format("The square root of {0} is {1}.",64,8);

// output: The square root of 64 is 8.

The method has several overloads, but this is the most common and illustrates two features common to all: a format string and a list of data arguments. Note that Console.WriteLine accepts the same parameters and can be used in place of String.Format for console output.

Constructing a Format Item

Figure 5-3 breaks down a String.Format example into its basic elements. The most interesting of these is the format item, which defines the way data is displayed.

Figure 5-3. String.Format example

As we can see, each format item consists of an index and an optional alignment and format string. All are enclosed in brace characters:

  1. The index is a zero-based integer that indicates the argument to which it is to be applied. The index can be repeated to refer to the same argument more than once.

  2. The optional alignment is an integer that indicates the minimum width of the area that contains the formatted value. If alignment value is positive, the argument value is right justified; if the value is negative, it is left justified.

  3. The optional format string contains the formatting codes to be applied to the argument value. If it is not specified, the output of the argument's ToString method is used. .NET provides several standard format codes to be used with numbers and dates as well as codes that are used to create custom format strings.

Formatting Numeric Values

Nine characters, or format specifiers, are available to format numbers into currency, scientific, hexadecimal, and other representations. Each character can have an integer appended to it that specifies a precision particular to that format梪sually this indicates the number of decimal places. C# recognizes the standard format specifiers[2] shown in Table 5-4.

[2] Microsoft Windows users can set formats using the Control Panel ?Regional Options settings.

Table 5-4. Formatting Numeric Values with Standard Numeric Format Strings

Format Specifier




C or c

Currency. Number is represented as a currency amount. The precision specifies the number of decimal places.

{0:C2}, 1458.75

$ 1,458.75

D or d

Decimal. Applies to integral values. The precision indicates the total number of spaces the number occupies; is padded with zeros on left if necessary.

{0:D5}, 455

{0:D5}, -455



E or e

Scientific. The number is converted to a scientific notation: ddddE+nnn. The precision specifies the number of digits after the decimal point.

{0,10:E2}, 3298.78

{0,10:E4}, -54783.4



F or f

Fixed Point. The number is converted to format of: ddd.ddd. The precision indicates the number of decimal places.

{0,10:F0}, 162.57

{0,10:F2}, 8162.57



G or g

General. The number is converted to fixed point or scientific notation based on the precision and type of number. Scientific is used if the exponent is greater than or equal to the specified precision or less than ?.

{0,10:G}, .0000099

{0,10:G2}, 455.89

{0,10:G3}, 455.89

{0,10:G}, 783229.34





N or n

Number. Converts to a string that uses commas as thousands separators. The precision specifies the number of decimal places.

{0,10:N}, 1045.78

{0,10:N1}, 45.98



P or p

Percent. Number is multiplied by 100 and presented as percent with number of decimal places specified by precision.

{0,10:P}, 0.78

{0,10:P3}, 0.7865

 78.00 %

78.650 %

R or r

Round-trip. Converts to a string that retains all decimal place accuracy. Then number to be converted must be floating point.

{0,10:R}, 1.62736


X or x

Hexadecimal. Converts the number to its hex representation. The precision indicates the minimum number of digits shown. Number is padded with zeros if needed.

{0,10:X}, 25

{0,10:X4}, 25

{0,10:x4}, 31




The patterns in this table can also be used directly with Console.Write and Console.WriteLine:

Console.WriteLine("The Hex value of {0} is {0:X} ",31); //1F

The format specifiers can be used alone to enhance output from the ToString method:

decimal pct = .758M;

Console.Write("The percent is "+pct.ToString("P2")); // 75.80 %

.NET also provides special formatting characters that can be used to create custom numeric formats. The most useful characters are pound sign (#), zero (0), comma (,), period (.), percent sign (%), and semi-colon (;). The following code demonstrates their use:

decimal dVal = 2145.88M;   // decimal values require M suffix

string myFormat;

myFormat = dVal.ToString("#####");           //  2146

myFormat = dVal.ToString("#,###.00");        //  2,145.88

myFormat = String.Format("Value is {0:#,###.00;


// semicolon specifies alternate formats. (4,567.00)

myFormat = String.Format("Value is {0:$#,###.00}", 4567);

                                             //  $4,567.00

Console.WriteLine("{0:##.00%}",.18);         //  18.00 %

The role of these characters should be self-explanatory except for the semicolon (;), which deserves further explanation. It separates the format into two groups: the first is applied to positive values and the second to negative. Two semicolons can be used to create three groups for positive, negative, and zero values, respectively.

Formatting Dates and Time

Date formatting requires a DateTime object. As with numbers, this object has its own set of standard format specifiers. Table 5-5 summarizes these.

Table 5-5. Formatting Dates with Standard Characters

Format Specifier





Short date pattern




Long date pattern

Monday, January 19, 2004

Montag, 19 Januar, 2004


Full date/time pattern (short time)

Monday, January 19, 2004 4:05 PM

Montag, 19 Januar, 2004 16:05


Full date/time pattern (full time)

Monday, January 19, 2004 4:05:20 PM

Montag, 19 Januar, 2004 16:05:20


General date/time pattern (short time)

1/19/2004 4:05 PM

19/1/2004 16:05


General date/time pattern (long time)

1/19/2004 4:05:20 PM

19/1/2004 16:05:20

M, m

Month day pattern

January 19

19 Januar

Y, y

Year month pattern

January, 2004

Januar, 2004


Short time pattern

4:05 PM



Long time pattern

4:05:20 PM



Universal Sortable Date-Time pattern. Conforms to ISO 8601. Uses local time.




Universal Sortable Date-Time pattern

2004-01-19 16:05:20Z

2004-01-19 16:05:20Z


Universal Sortable Date-Time pattern. Uses universal time.

Monday, January 19, 2004 21:05:20 PM

Montag, 19. Januar, 2004 21:05:20

Here are some concrete examples that demonstrate date formatting. In each case, an instance of a DateTime object is passed an argument to a format string.

DateTime curDate = DateTime.Now;  // Get Current Date

Console.Writeline("Date: {0:d} ", curDate);   // 1/19/2004

// f: --> Monday, January 19, 2004 5:05 PM

Console.Writeline("Date: {0:f} ", curDate);

// g: --> 1/19/2004 5:05 PM

Console.Writeline("Date: {0:g} ", curDate);

If none of the standard format specifiers meet your need, you can construct a custom format from a set of character sequences designed for that purpose. Table 5-6 lists some of the more useful ones for formatting dates.

Table 5-6. Character Patterns for Custom Date Formatting





Day of month. No leading zero.



Day of month. Always has two digits.



Day of week with three-character abbreviation.



Day of week full name.



Month number. No leading zero.



Month number with leading zero if needed.



Month name with three-character abbreviation.



Full name of month.



Year. Last one or two digits.



Year. Last one or two digits with leading zero if needed.



Four-digit year.



Hour in 24-hour format.



Minutes with leading zero if needed.


Here are some examples of custom date formats:

DateTime curDate = DateTime.Now;

f = String.Format("{0:dddd} {0:MMM} {0:dd}", curDate);

// output: Monday Jan 19

f = currDate.ToString("dd MMM yyyy")

// output: 19 Jan 2004

// The standard short date format (d) is equivalent to this:

Console.WriteLine(currDate.ToString("M/d/yyyy"));  // 1/19/2004

Console.WriteLine(currDate.ToString("d"));         // 1/19/2004

CultureInfo ci = new CultureInfo("de-DE");         // German

f = currDate.ToString("dd-MMMM-yyyy HH:mm", ci)

// output: 19-Januar-2004 23:07

ToString is recommended over String.Format for custom date formatting. It has a more convenient syntax for embedding blanks and special separators between the date elements; in addition, its second parameter is a culture indicator that makes it easy to test different cultures.

Dates and Culture

Dates are represented differently throughout the world, and the ability to add culture as a determinant in formatting dates shifts the burden to .NET from the developer. For example, if the culture on your system is German, dates are automatically formatted to reflect a European format: the day precedes the month; the day, month, and year are separated by periods (.) rather than slashes (/); and the phrase Monday, January 19 becomes Montag, 19. Januar. Here is an example that uses ToString with a German CultureInfo parameter:

CultureInfo ci = new CultureInfo("de-DE");       // German


// output ---> Montag, 19. Januar 2004

Console.WriteLine(curDate.ToString("dddd",ci));  // -->Montag

The last statement uses the special custom format "dddd" to print the day of the week. This is favored over the DateTime.DayofWeek enum property that returns only an English value.

NumberFormatInfo and DateTimeFormatInfo Classes

These two classes govern how the previously described format patterns are applied to dates and numbers. For example, the NumberFormatInfo class includes properties that specify the character to be used as a currency symbol, the character to be used as a decimal separator, and the number of decimal digits to use when displaying a currency value. Similarly, DateTimeFormatInfo defines properties that correspond to virtually all of the standard format specifiers for dates. One example is the FullDateTimePattern property that defines the pattern returned when the character F is used to format a date.

NumberFormatInfo and DateTimeFormatInfo are associated with specific cultures, and their properties are the means for creating the unique formats required by different cultures. .NET provides a predefined set of property values for each culture, but they can be overridden.

Their properties are accessed in different ways depending on whether the current or non-current culture is being referenced (current culture is the culture associated with the current thread). The following statements reference the current culture:



The first statement uses the static property CurrentInfo and implicitly uses the current culture. The second statement specifies a culture explicitly (CurrentCulture) and is suited for accessing properties associated with a non-current CultureInfo instance.

CultureInfo ci = new CultureInfo("de-DE");

string f = ci.NumberFormat.CurrencySymbol;

NumberFormatInfo and DateTimeFormatInfo properties associated with a non-current culture can be changed; those associated with the current thread are read-only. Listing 5-3 offers a sampling of how to work with these classes.

Listing 5-3. Using NumberFormatInfo and DateTimeFormatInfo

using System

using System.Globalization

Class MyApp


   // NumberFormatInfo

   string curSym = NumberFormatInfo.CurrentInfo.CurrencySymbol;

   int dd  = NumberFormatInfo.CurrentInfo.CurrencyDecimalDigits;

   int pdd = NumberFormatInfo.CurrentInfo.PercentDecimalDigits;

   // --> curSym = "$"   dd = 2  pdd = 2

   // DateTimeFormatInfo

   string ldp= DateTimeFormatInfo.CurrentInfo.LongDatePattern;

   // --> ldp = "dddd, MMMM, dd, yyyy"

   string enDay = DateTimeFormatInfo.CurrentInfo.DayNames[1];

   string month = DateTimeFormatInfo.CurrentInfo.MonthNames[1];

   CultureInfo ci = new CultureInfo("de-DE");

   string deDay = ci.DateTimeFormat.DayNames[1];

   // --> enDay = "Monday"  month = February  deDay = "Montag"

   // Change the default number of decimal places

   // in a percentage

   decimal passRate = .840M;

   Console.Write(passRate.ToString("p",ci));  // 84,00%

   ci.NumberFormat.PercentDecimalDigits = 1;

   Console.Write(passRate.ToString("p",ci));  // 84,0%


In summary, .NET offers a variety of standard patterns that satisfy most needs to format dates and numbers. Behind the scenes, there are two classes, NumberFormatInfo and DateTimeFormatInfo, that define the symbols and rules used for formatting. .NET provides each culture with its own set of properties associated with an instance of these classes.

    Previous Section  < Day Day Up >  Next Section