30 Days Of .NET 6 - DateOnly Type
[C#, .NET, 30 Days Of .NET 6]
In .NET when manipulating dates and times, you generally use the DateTime type for such purposes.
This generally works but can be a bit clumsy and can trip you up do to the fact that a DateTime
contains a date and a time component.
Strictly speaking this is not incorrect - the two are completely interrelated.
However there are times when you are only interested in the date and the time is a distraction. For example you want to know orders placed today - regardless of the time.
I have discussed this briefly in a previous post but in .NET 6 there is an even better solution to this problem - the DateOnly type.
It is very similar to a DateTime
object at first glance - it just omits all the time details.
var newDate = new DateOnly(2022, 1, 1);
You can also get a DateOnly
instance form an existing DateTime
object.
var otherNewDate = DateOnly.FromDateTime(DateTime.Now);
You can also get a DateOnly
form a day number - where day 0 is 1 January 0000
var dayZero = DateOnly.FromDayNumber(0);
DateOnly
also has the Parse
, TryParse
and ParseExect
methods to allow construction from strings.
var christmas = DateOnly.ParseExact("2021-12-25", "yyyy-MM-dd");
In terms of operations the DateOnly
supports the usual manipulations - Adding or subtracting the relevant properties - Day, Month and Year.
For example, to get the DateOnly
a year from an existing DateOnly
object:
var nextYear = newDate.AddYears(1);
(Note: subtraction is done by adding a negative number)
Finally, the DateOnly
object by default works with the Gregorian Calendar. However there is an overload that allows you to construct a DateOnly
from any supported calendar.
For example, to use a Persian calendar, you construct a DateOnly
as follows:
var persianCalendar = new PersianCalendar();
var persianCurrentDate = new DateOnly(2021, 1, 1, persianCalendar);
Console.WriteLine(persianCurrentDate);
This should generate the following:
21 Mar 2642
You might wonder why it was called DateTime
and not just Date
.
A couple of reasons:
- In Visual Basic .NET Date is an alias for the
DateTime
type. - There is already a Date property of the
DateTime
type, which is also aDateTime
(but with the time component set to midnight)
The DateOnly
type also has a number of handy properties that make general coding easier:
Thoughts
This is an excellent, long overdue type
-
It communicates clearly the intent of the developer (I am only interested in the date, regardless of the time)
-
It will avoid all sorts of logic bugs when using a normal
DateTime
.For example innocent looking code like this often fails
var ordersPlacedToday = allOrders.Where(x => x.OrderDate == DateTime.Now)
Why? Because DateTime.Now has a
Time
component and this query will almost always fail because in the data sourceOrderDate
is set to midnight butDateTime.Now
will return in addition to the date the current time down to milliseconds, making the evaluation fail.
Would be interesting to understand the rationale of why this
var otherNewDate = DateOnly.FromDateTime(DateTime.Now);
was chosen rather than this:
var otherNewDate = DateTime.Now.ToDateOnly();
I think the latter is more discoverable to current users.
TLDR
There is a new DateOnly type that unlike the DateTime that deals with dates and time, only deals with the date.
The code is in my Github.
This is Day 1 of the 30 Days Of .NET 6 where every day I will attempt to explain one new / improved thing in the upcoming release of .NET 6.
Happy hacking!