1. Introduction
Back in the day, C# didn't have a separate type for just a date or just a time. So even if you only needed to store a date—like a birthday—you had to use DateTime and tack on a "default time". The old way to store just a date using DateTime:
DateTime birthday = new DateTime(1985, 4, 20); // April 20, 1985, 00:00:00
But that's not convenient. You just want a date, but you end up with a time too—even if it's zero. That can be confusing: for example, when comparing dates, your program might take the time into account and you'll get weird results.
Same story the other way around: if you're only working with time (like a work schedule from 08:00 to 17:00), you still had to "make up" a date, even though it doesn't matter at all.
Now .NET has special types DateOnly and TimeOnly that get rid of all that confusion.
New Handy Types DateOnly and TimeOnly
- DateOnly — just a calendar date, no time of day and no timezone info.
- TimeOnly — just the time of day, no year, month, day, and again, no timezone.
Time Types Comparison Table
| Type | Date | Time | Timezone | What is it used for? |
|---|---|---|---|---|
|
✅ | ✅ | 🚫 | Pretty much everything (but not always convenient or safe) |
|
✅ | ✅ | ✅ | When you need both a moment in time and a timezone |
|
✅ | 🚫 | 🚫 | Birthdays, dates without time |
|
🚫 | ✅ | 🚫 | Business hours, schedules, intervals during the day |
2. Working with DateOnly
Declaration and Creation
Creating a DateOnly object is as easy as picking up a new habit: quick and simple! For example:
// Year, month, day
DateOnly birthday = new DateOnly(1985, 4, 20);
You can use DateOnly.FromDateTime if you already have a DateTime object:
DateTime now = DateTime.Now;
DateOnly today = DateOnly.FromDateTime(now);
// now today only has the date, time is dropped
Main Properties and Methods
- Year, Month, Day — just like in DateTime.
- .ToString() — formats the date, you can set your own format.
Console.WriteLine($"Birthday: {birthday.Year} year, {birthday.Month} month, {birthday.Day} day.");
Console.WriteLine(today.ToString("dd.MM.yyyy")); // For example, 07/30/2024
Date Math
You can easily add days/months/years:
DateOnly tomorrow = today.AddDays(1);
DateOnly nextMonth = today.AddMonths(1);
Try swapping out your DateTime fields that only store a date for DateOnly in your main app—you'll be one step closer to modern .NET!
Date Comparison
You can compare using <, >, ==:
if (birthday < today)
Console.WriteLine("Birthday already happened this year or a long time ago :)");
No more bugs with extra milliseconds or minutes.
Getting Today's Date
DateOnly currentDate = DateOnly.FromDateTime(DateTime.Now);
3. Working with TimeOnly
Now let's deal with time without a date—because what programmer hasn't had to deal with lunch schedules?
Creating TimeOnly
TimeOnly startWork = new TimeOnly(9, 0); // 09:00
TimeOnly endWork = new TimeOnly(17, 30); // 17:30
You can get just the hours, minutes, seconds:
Console.WriteLine($"Workday: from {startWork.Hour}:{startWork.Minute:D2} to {endWork.Hour}:{endWork.Minute:D2}");
Get Time from DateTime
DateTime now = DateTime.Now;
TimeOnly currentTime = TimeOnly.FromDateTime(now);
Console.WriteLine($"Right now it's {currentTime}");
Time Math
TimeOnly breakStart = startWork.AddHours(4); // break in 4 hours, so at 13:00
TimeOnly breakEnd = breakStart.AddMinutes(30); // 30 minute lunch
Comparisons and Checks
if (currentTime >= startWork && currentTime <= endWork)
Console.WriteLine("Time to work :)");
else
Console.WriteLine("You can chill.");
4. Interacting with Other Types
Converting between DateOnly, TimeOnly, and DateTime
Sometimes you need to get a DateTime again (like for storing in an old database or for compatibility):
DateOnly datePart = new DateOnly(2024, 7, 30);
TimeOnly timePart = new TimeOnly(14, 15);
DateTime datetime = datePart.ToDateTime(timePart); // 2024-07-30 14:15:00
And the other way around:
DateTime dt = DateTime.Now;
DateOnly justDate = DateOnly.FromDateTime(dt);
TimeOnly justTime = TimeOnly.FromDateTime(dt);
Important Features and Common Mistakes
- If you try to parse just a date or just a time using the old methods like DateTime.Parse(), you'll probably get an error or not what you expected. For those cases, there are special methods: use DateOnly.Parse() and TimeOnly.Parse()—they know how to handle "trimmed" values.
- Important to get: DateOnly and TimeOnly have zero clue about timezones. It's just a date or just a time—no connection to a timezone. If you need to care about zones, store that info separately.
GO TO FULL VERSION