DateOnly in your .NET 6 API

Let's face it: sometimes DateTime is just too much: you only want to deal with dates. Since .NET 6, we finally have support for DateOnly. In this blog I'll look at how to interact with it and how to add it to your Swagger API docs.

To and From DateTime

It is nice that we have a DateOnly, but there are plenty of occasions you'll need that good ol DateTime back. Converting them back and forth is easy:

// let's convert DateTime to DateOnly
var day = DateOnly.FromDateTime(DateTime.Now);

// let's convert DateOnly to DateTime
var dt = day.ToDateTime(new TimeOnly());

Time travel with DateOnly

I need to work with months, so I'm interested in getting the first and the last date of the month. The following code was airlifted and adjusted from StackOverflow:

public static class TimeTravelExtensions
{
    public static DateOnly FirstDayOfMonth(this DateOnly value) => new DateOnly(value.Year, value.Month, 1);

    public static int DaysInMonth(this DateOnly value) => DateTime.DaysInMonth(value.Year, value.Month);

    public static DateOnly LastDayOfMonth(this DateOnly value) => new DateOnly(value.Year, value.Month, value.DaysInMonth());

    public static DateOnly FirstDayOfWeek(this DateOnly value) => value.AddDays(-(int)value.DayOfWeek);
}

DateOnly Web API support

The Web API doesn't have great support out of the box. I just want to use DateOnly like any other data structure (a string will do). Also, I would like Swagger (openapi) to understand it. Fortunately, there are packages that will give you great support:

  • Install-Package DateOnlyTimeOnly.AspNet -Version 1.0.3
    Install-Package DateOnlyTimeOnly.AspNet.Swashbuckle -Version 1.0.3
  • dotnet add package DateOnlyTimeOnly.AspNet --version 1.0.3
    dotnet add package DateOnlyTimeOnly.AspNet.Swashbuckle --version 1.0.3
  • <PackageReference Include="DateOnlyTimeOnly.AspNet" Version="1.0.3" />
    <PackageReference Include="DateOnlyTimeOnly.AspNet.Swashbuckle" Version="1.0.3" />

Add it to your dependency injection:

services
    .AddControllers(options => options.UseDateOnlyTimeOnlyStringConverters())
    .AddJsonOptions(options => options.UseDateOnlyTimeOnlyStringConverters());

Add it to Swagger:

services.AddSwaggerGen(options =>
{
    options.UseDateOnlyTimeOnlyStringConverters();
});

According to the docs, this will add "support for receiving and returning DateOnly/TimeOnly as ISO 8601 string to ASP.NET API". It will look something like this:

A screenshot of a Swagger/Open API interface, showing how to work with DateOnly when using DateOnlyTimeOnly.AspNet.Swashbuckle.
The input value is DateOnly and is shown with type string($date). The output day is shown in the ISO 8601 format.
expand_less