DateTime is the type C# uses for a point in time. It carries a date, a time and a Kind, which says whether that value is local, UTC or unspecified. Unspecified is the default, and it is the cause of most date bugs in .NET applications.

Store UTC, display local, and use DateTimeOffset whenever the offset from UTC is part of what you need to keep. If you only need a calendar date with no time attached, use DateOnly, which arrived in .NET 6 and removes a whole class of off-by-one-hour problems.

DateTime is a struct, so it is a value type and it is immutable. AddDays does not change your variable, it hands you a new DateTime.

Everything below, from formatting through to the awkward calendar arithmetic.

Choosing the Right Date Type

Read this section first. Most date bugs come from picking the wrong type.

Formatting and Parsing

Turning a DateTime into text and text back into a DateTime.

Comparing Dates and Date Ranges

Asking which came first, and whether two periods touch.

Calendar Arithmetic

The calculations that look trivial and are not, because months and weeks are not fixed lengths.

Timers, Stopwatches and Storage

Measuring elapsed time, running work on a schedule, and getting dates in and out of a database.

Where to Go Next

Dates usually come from, or end up in, one of these:

Whatever you store, store the same thing everywhere. Half your rows in UTC and half in local time is the kind of bug that stays hidden until the clocks change.