String Formatting - Formatting Numbers, Dates, and Text in C#
Vaibhav • September 10, 2025
String formatting is about turning raw data-numbers, dates, and other values-into clear, readable text for
users, logs, files, and reports. In C#, formatting is built into string interpolation, the string.Format
method, and many type-specific ToString()
overloads. This article covers the most useful formatting patterns for
numbers, dates, currency, alignment, and custom patterns, with practical examples and best practices for
everyday code.
This article builds on string interpolation and concatenation. We’ll focus on format specifiers, alignment, culture, and common formatting tasks you’ll encounter in real projects.
1) Formatting numbers - decimals, thousands, currency, percentages
Use format specifiers inside interpolation braces or with ToString()
to control
how numbers appear.
double price = 1234.567;
int quantity = 42;
double percent = 0.876;
string s1 = $"Price: {price:F2}"; // "Price: 1234.57" (2 decimals)
string s2 = $"Qty: {quantity:D4}"; // "Qty: 0042" (pad with zeros)
string s3 = $"Total: {price:N0}"; // "Total: 1,235" (thousands separator)
string s4 = $"Discount: {percent:P1}"; // "Discount: 87.6%" (percentage, 1 decimal)
string s5 = $"Hex: {quantity:X}"; // "Hex: 2A" (hexadecimal)
F2
- fixed-point, 2 decimalsN0
- number, no decimals, thousands separatorP1
- percentage, 1 decimalD4
- decimal, pad to 4 digitsX
- hexadecimal
2) Formatting dates and times - custom patterns
Dates and times can be formatted with custom patterns inside interpolation or ToString()
.
DateTime now = DateTime.Now;
string s1 = $"Date: {now:yyyy-MM-dd}"; // "Date: 2025-09-10"
string s2 = $"Time: {now:HH:mm:ss}"; // "Time: 15:30:45"
string s3 = $"Full: {now:dd-MMM-yyyy HH:mm}"; // "Full: 10-Sep-2025 15:30"
string s4 = $"Day: {now:dddd}"; // "Day: Wednesday"
yyyy
- year (4 digits)MM
- month (2 digits)dd
- day (2 digits)HH
- hour (24-hour)mm
- minutess
- seconddddd
- day of weekMMM
- abbreviated month name
3) Alignment and width - neat columns and tables
Use a comma and a number inside interpolation braces to align output. Positive numbers right-align, negative numbers left-align.
string[] names = { "Ada", "Grace", "Linus" };
int[] scores = { 95, 100, 89 };
Console.WriteLine($"{"Name",-10} {"Score",5}");
Console.WriteLine(new string('-', 16));
for (int i = 0; i < names.Length; i++)
Console.WriteLine($"{names[i],-10} {scores[i],5}");
/*
Name Score
----------------
Ada 95
Grace 100
Linus 89
*/
{expr,-10}
- left-align in 10 spaces{expr,5}
- right-align in 5 spaces- Combine alignment and formatting:
{score,6:F1}
4) Formatting currency and culture-sensitive values
Use C
for currency, and specify culture for consistent output.
double amount = 1234.5;
string s1 = $"Amount: {amount:C}"; // "Amount: ₹1,234.50" (depends on system culture)
using System.Globalization;
string s2 = amount.ToString("C", CultureInfo.InvariantCulture); // "Amount: $1,234.50"
C
- currency format (symbol depends on culture)- Use
CultureInfo.InvariantCulture
for logs, data files, or tests
For user-facing text, use the current culture. For machine-readable output, prefer invariant culture for consistency.
5) Formatting with string.Format
- legacy but still useful
string.Format
lets you use numbered placeholders and format specifiers. It’s
less common now (interpolation is preferred), but you’ll see it in older code and some APIs.
int id = 42;
double value = 123.456;
string formatted = string.Format("ID={0:D4}, Value={1:F2}", id, value); // "ID=0042, Value=123.46"
{0:D4}
- first argument, pad to 4 digits{1:F2}
- second argument, 2 decimals
6) Custom patterns - building your own formats
You can combine formatting patterns for custom output, such as CSV lines, logs, or reports.
string[] fields = { "Ada", "Lovelace", "Mathematician" };
string csv = string.Join(",", fields); // "Ada,Lovelace,Mathematician"
DateTime dt = DateTime.Now;
string log = $"[{dt:yyyy-MM-dd HH:mm:ss}] {csv}";
Console.WriteLine(log);
// "[2025-09-10 15:30:45] Ada,Lovelace,Mathematician"
7) Defensive formatting - handling nulls, empty values, and errors
- Nulls: Interpolation inserts an empty string for
null
variables. Still, validate user input before formatting. - Empty strings: Use
string.IsNullOrEmpty()
to check before formatting. - Exceptions: Invalid format specifiers cause runtime errors. Test your patterns with sample data.
8) Practical mini-project: formatted invoice line
string item = "Widget";
int qty = 7;
double unitPrice = 19.99;
double total = qty * unitPrice;
string line = $"{item,-10} {qty,3} x {unitPrice,8:C2} = {total,10:C2}";
Console.WriteLine(line);
// "Widget 7 x ₹19.99 = ₹139.93"
- Left-align item name, right-align quantity, format price and total as currency with 2 decimals.
- Easy to scan, easy to audit, and ready for printing or exporting.
9) Quick reference - most useful format specifiers
F2
- fixed-point, 2 decimalsN0
- number, no decimals, thousands separatorP1
- percentage, 1 decimalC
- currencyD4
- decimal, pad to 4 digitsX
- hexadecimalyyyy-MM-dd
- date (year-month-day)HH:mm:ss
- time (24-hour)dd-MMM-yyyy
- date (day-abbreviated month-year)
10) Checklist - formatting habits for better code
- Use interpolation for most formatting tasks (
$"..."
). - Specify format strings for numbers and dates inside braces (
{expr:format}
). - Align columns with
{expr,width}
for neat tables. - Use
string.Join
for lists and CSV lines. - Control culture for logs, exports, and tests.
- Validate input before formatting to avoid nulls and errors.
- Test your format patterns with sample data.
Summary
String formatting in C# lets you turn raw data into clear, professional output. Use interpolation and format specifiers for numbers, dates, currency, and alignment. Combine patterns for custom reports, logs, and exports. Control culture for consistent output, and validate input to avoid surprises. With these habits, your code will be easier to read, audit, and maintain-no matter how complex your data gets.