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.
- DateTimeOffset vs DateTime
- Difference Between DateTime.Now and DateTime.UtcNow
- DateOnly and TimeOnly
- TimeSpan
- How to Map DateOnly and TimeOnly Types to SQL
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.
- Compare DateTime
- Determine Whether Two Date Ranges Overlap
- How to Check if a Date Is On or Before Today
Calendar Arithmetic
The calculations that look trivial and are not, because months and weeks are not fixed lengths.
- Check if DateTime Is Weekend or Weekday
- How to Calculate the Number of Days Between Two Dates
- Calculate the Difference in Months Between Two Dates
- How to Get the Quarter of a Given Date
- How to Get the Date of the First Day in a Week
- How to Get the Number of Weekdays Between Two Dates
Timers, Stopwatches and Storage
Measuring elapsed time, running work on a schedule, and getting dates in and out of a database.
- PeriodicTimer
- Timer
- DateTime Calendars
- Convert DateTime to ISO 8601 String
- Remove Time From a DateTime Object
- How to Use Stopwatch
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.
