CodeGym /Courses /C# SELF /Formatting and Parsing Dates and Times

Formatting and Parsing Dates and Times

C# SELF
Level 15 , Lesson 3
Available

1. Formatting Dates

If you think output like 2025-06-19T17:30:00 looks pretty slick, try showing that format to your grandma or your accountant. Odds are, they'll want something simpler: 19.06.2025 17:30. But your English-speaking coworkers expect 06/19/2025 5:30 PM. DevOps folks and machines? They love 2025-06-19T17:30:00Z. So, a single DateTime in your program's memory can show up in dozens of formats on the screen.

The reverse task is classic too: a user enters a date in an input field ("19.06.2025"), and we need to recognize it as a C# object and not get confused about which is the day and which is the month. Automation, integrations, reports — everywhere you need to interpret text dates correctly.

Basic Formatting

C# lets you convert a date/time object (DateTime, DateOnly, TimeOnly, DateTimeOffset) to a string using the .ToString() method:


DateTime now = DateTime.Now;
Console.WriteLine(now.ToString()); // Output: 19.06.2025 17:30:25
Basic date and time formatting

If you call .ToString() with no parameters, you'll get the format typical for your system's current culture (for example, German Windows will show one format, American Windows — another).

Standard Format Strings

You can explicitly set the output format using so-called standard date and time format strings:

Format Description Sample Output
"d"
Short date 19.06.2025
"D"
Long date June 19, 2025
"f"
Long date + short time June 19, 2025 17:30
"F"
Long date + long time June 19, 2025 17:30:25
"g"
Short date and time 19.06.2025 17:30
"G"
Short date + long time 19.06.2025 17:30:25
"t"
Short time 17:30
"T"
Long time 17:30:25
"M"/"m"
Month and day June 19
"Y"/"y"
Year and month June 2025
"O"/"o"
ISO 8601 (round tripper) 2025-06-19T17:30:25.0000000

Console.WriteLine(now.ToString("d")); // 19.06.2025
Console.WriteLine(now.ToString("F")); // June 19, 2025 17:30:25
Console.WriteLine(now.ToString("O")); // 2025-06-19T17:30:25.0000000

Custom Patterns

If you need more specific formats, you can use your own patterns:

Symbol Meaning
yyyy Year, 4 digits
yy Year, 2 digits
MM Month, 2 digits
MMMM Month name
dd Day, 2 digits
d Day, 1-2 digits
HH Hour (24h)
mm Minutes
ss Seconds
tt AM/PM

Console.WriteLine(now.ToString("yyyy-MM-dd HH:mm")); // 2025-06-19 17:30
Console.WriteLine(now.ToString("dd.MM.yyyy"));       // 19.06.2025
Console.WriteLine(now.ToString("dddd, MMMM d"));     // Wednesday, June 19

Cultural Differences in Formatting

If you want to get the result in another country's or language's style, use the overload ToString(string, IFormatProvider):


var enUS = new System.Globalization.CultureInfo("en-US");
Console.WriteLine(now.ToString("D", enUS)); // June 19, 2025
  • If you hardcode a pattern like "MM/dd/yyyy", then no matter the culture, you'll still get "06/19/2025".
  • But if you use just "d" or "D" — the format depends on the culture!

Important Points When Formatting

When working with date formatting, it's important to understand the difference between standard and custom formats. Standard formats (like "d", "F", "G") automatically adapt to the system's culture, which is handy for user interfaces, but can cause trouble when exchanging data between systems. Custom formats give you full control over the output, but require more detailed setup.

Pay special attention to the "O" (or "o") format — this is the so-called "round-trip" format, which guarantees that a date converted to a string and back will stay exactly the same. This format is especially important when serializing data or sending it over the network.

2. Parsing Dates and Times: How to Get an Object from a String

Simple Parsing: DateTime.Parse

DateTime.Parse is a method that tries to recognize a date string, taking the system's culture into account.


string input = "19.06.2025";
DateTime parsed = DateTime.Parse(input);
Console.WriteLine(parsed); // 19.06.2025 00:00:00

If the string is invalid — the program will crash with an exception (nobody's safe!).

Specifying Culture


string input = "06/19/2025";
var enUS = new System.Globalization.CultureInfo("en-US");
DateTime dt = DateTime.Parse(input, enUS);
Console.WriteLine(dt); // 19.06.2025 00:00:00

Safe Parsing: TryParse


string input = "invalid date";
bool ok = DateTime.TryParse(input, out DateTime safeDate);
if (!ok)
    Console.WriteLine("Error: couldn't recognize the date!");

Strict Format: ParseExact and TryParseExact


var culture = System.Globalization.CultureInfo.InvariantCulture;
string dateStr = "2025-06-19";

DateTime d = DateTime.ParseExact(dateStr, "yyyy-MM-dd", culture);
Console.WriteLine(d); // 19.06.2025 00:00:00

bool parsedOk = DateTime.TryParseExact(
    "19.06.2025",
    "dd.MM.yyyy",
    System.Globalization.CultureInfo.InvariantCulture,
    System.Globalization.DateTimeStyles.None,
    out DateTime myDate);

Popular Formats Table

String Format Resulting Object
"2025-06-19" "yyyy-MM-dd" June 19, 2025
"19.06.2025" "dd.MM.yyyy" June 19, 2025
"06/19/2025" "MM/dd/yyyy" June 19, 2025
"2025-06-19T14:15:16" "s" June 19, 2025 14:15:16

Working with DateTimeStyles

When parsing, you can further control behavior using the DateTimeStyles parameter. This enum lets you set how the parser should interpret the input. For example, DateTimeStyles.AssumeUniversal makes the parser treat the time as UTC if the offset isn't specified. DateTimeStyles.AllowWhiteSpaces lets you ignore extra spaces in the string. These settings are especially useful when working with data from external sources, where the format might not be totally predictable.

3. Formatting and Parsing DateOnly, TimeOnly

The new types DateOnly and TimeOnly are now often used to store dates/times without extra details.

Formatting


DateOnly birthday = new DateOnly(2000, 6, 19);
Console.WriteLine(birthday.ToString("dd MMMM yyyy")); // 19 June 2000

Parsing


var d = DateOnly.ParseExact("19.06.2000", "dd.MM.yyyy");
Console.WriteLine(d.Day); // 19

The same methods work for TimeOnly (except the patterns are just about hours/minutes/seconds):

TimeOnly t = TimeOnly.ParseExact("23:59", "HH:mm");
Console.WriteLine(t.Hour); // 23

Advantages of DateOnly and TimeOnly

Using DateOnly and TimeOnly instead of DateTime gives you a few important advantages. First, it's semantically clear — if you only need a date without a time (like a birthday), DateOnly makes that intent obvious. Second, it helps you avoid timezone issues that can pop up with DateTime. Third, these types take up less space in memory and databases.

Formatting and Parsing with Timezones

If you're storing time with offset info — use DateTimeOffset. This is especially important for international, distributed systems. All the formatting and parsing methods are the same, but now you can also control the offset:


DateTimeOffset meeting = new DateTimeOffset(2025, 6, 19, 17, 30, 0, TimeSpan.FromHours(3));
Console.WriteLine(meeting.ToString("o")); // 2025-06-19T17:30:00.0000000+03:00

string input = "2025-06-19T17:30:00+03:00";
var parsedOffset = DateTimeOffset.Parse(input);
Console.WriteLine(parsedOffset.Offset); // 03:00:00

4. Practical Notes and Common Mistakes

One of the traps is mixing up "day" and "month" when parsing international formats. For example, the string "01/02/2025" in the US is January 2, but in most European countries it's February 1 (surprise!).

People also often forget about the effect of culture: if your app is running on a server in Germany, but users are from different countries, the date format from the database might be interpreted differently on each server.

A common mistake is using .ToString() without specifying culture/format for logs and data exchange files: the result might change after migrating to another OS or if the app runs under a different Windows user.

Tips for Working with Dates

  • For internal storage and data exchange, always use invariant culture (CultureInfo.InvariantCulture) or explicitly specified formats.
  • For user interfaces, use the user's culture or let them pick their preferred format.
  • When working with APIs and databases, prefer the ISO 8601 format, which is the international standard.
  • Always validate input: check if the date exists, the range, and if the values make sense.

Working with Different Data Sources

When integrating with external systems, you often have to deal with dates in different formats. Some systems might send dates as Unix timestamps (number of seconds since January 1, 1970), others — as strings in national formats. It's important to agree on a data exchange format ahead of time and always check parsing correctness.

Also remember that some formats can be ambiguous. For example, "12/13/2025" is clearly December 13, 2025, but "12/11/2025" could be either December 11 or November 12 depending on the culture. In such cases, it's better to use less ambiguous formats or explicitly specify the parsing culture.

2
Task
C# SELF, level 15, lesson 3
Locked
Basic date and time formatting
Basic date and time formatting
2
Task
C# SELF, level 15, lesson 3
Locked
Safe date parsing from a string
Safe date parsing from a string
Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION