Working with Dates and Time in C#: Advanced Techniques and Tips

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Advanced Work with Dates and Time in C#: From Theory to Real-World Tasks

Working with dates and time is one of the most common and simultaneously tricky tasks in development. At a basic level, we simply create DateTime.Now and output it to the console. But when a project outgrows toy-like boundaries, complexities arise: daylight saving time, different time zones, high-precision calculations, or the need to work with dates without a time zone. In this article, we will cover advanced techniques for working with dates and time in C# (.NET) that will help you write reliable and predictable code.



1. DateTime, DateTimeOffset, and TimeSpan: Choosing the Right Tool

Many developers use DateTime by default without thinking about its limitations. At an advanced level, it is important to understand the difference between the three main types.



DateTime

Stores a date and time. Its main problem is ambiguity. The Kind property (Local, Utc, Unspecified) is not always set explicitly, leading to errors during serialization or comparison.



DateTimeOffset

Stores a date, time, and offset from UTC. This is the recommended type for storing moments in time, as it unambiguously defines a point on the timeline. For example, 2025-03-15T14:00:00+03:00 is always a specific moment, regardless of the user's time zone.



TimeSpan

Represents a time interval, not a specific moment. Used for arithmetic: difference between dates, timeouts, operation duration.



// Example: DateTime vs DateTimeOffsetDateTime localNow = DateTime.Now; // Kind = LocalDateTime utcNow = DateTime.UtcNow; // Kind = Utc

DateTimeOffset preciseNow = DateTimeOffset.Now; // Always with offset indication

// Comparison: DateTimeOffset is more unambiguousConsole.WriteLine(preciseNow.Offset); // +03:00 or -05:00 etc.


Tip: For new projects, use DateTimeOffset for storing moments in time, TimeSpan for intervals, and DateTime only when truly necessary (e.g., for compatibility with legacy code).



2. Parsing and Formatting: How to Avoid FormatException

Parsing dates from strings is a source of many errors, especially if the strings come from users or different cultures.



Culture-Dependent Parsing

Use CultureInfo.InvariantCulture for internal data exchange (e.g., JSON, API). For user input, consider the user's culture.



// Parsing with culture awarenessstring dateString = "15.03.2025";var ruCulture = new CultureInfo("ru-RU");DateTime parsedDate = DateTime.Parse(dateString, ruCulture);

// Invariant parsing (recommended for API)string isoString = "2025-03-15T14:00:00Z";DateTimeOffset parsedIso = DateTimeOffset.Parse(isoString, CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind);


TryParseExact for Reliability

If the string format is known, use TryParseExact with an explicit format. This eliminates unexpected exceptions.



string input = "2025-03-15 14:30";string format = "yyyy-MM-dd HH:mm";if (DateTime.TryParseExact(input, format, CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime result)){    Console.WriteLine($"Success: {result}");}else{    Console.WriteLine("Parsing error");}


Custom Formatting

Standard specifiers (d, D, t, T) are good, but for precise control, use custom format strings.



DateTime now = DateTime.Now;Console.WriteLine(now.ToString("yyyy-MM-dd HH:mm:ss.fff")); // 2025-03-15 14:30:45.123Console.WriteLine(now.ToString("dd MMMM yyyy, dddd"));      // 15 March 2025, Saturday

Blogs

Book Recommendations