How to Use Dates with React.js and .NET 5.0

March 1st 2021 ·  By Daniel Karpienia ·  4 min read ·  680 words

Implementing dates can be tricky with different local date formatting and client-side time zones. That is why I recommend using UTC date format on the client-side and converting it to your local date and time in the backend. Doing this you don't run into formatting issues regardless of geographical locations or date time formats. At first this may seem difficult but with component libraries implementation becomes simple.

Setup Your Date Control

For most projects I use Material UI. The controls have a great look and feel and integrate easily with React.js.

To install Material UI, Material UI Pickers and its dependencies run the following install command:

npm i @material-ui/core @material-ui/pickers @date-io/date-fns@1.3.13 date-fns

I am using date-fns@1.3.13 because of a formatting issue in 2+ versions.

Import the following references at the top your class:

import DateFnsUtils from "@date-io/date-fns";
import { DateTimePicker, MuiPickersUtilsProvider } from "@material-ui/pickers";

Use a state hook to keep track of the date value:

const [date, setDate] = useState(new Date());

Now you can use the DateTimePicker component as follows:

<MuiPickersUtilsProvider utils={DateFnsUtils}>
    <DateTimePicker
        label="Date"
        inputVariant="outlined"
        value={date}
        fullWidth
        onChange={(date) => setDate(date)}
    />
</MuiPickersUtilsProvider>

With this setup the date value is going to be in UTC date format and the conversion will happen in your .NET controller.

Create Controller Endpoint in .NET 5.0

Create a new controller class with a route that matches \api\demo\date:

public class DemoController : Controller
{
    [HttpPost("date")]
    public IActionResult ConvertDate([FromBody] Payload payload)
    {
        return Ok();
    }
}

Notice we did not implement the function body yet. We are using it as a place holder to test our front end code first.

A good practice is first setup your endpoint and test using Postman before writing your frontend code. This way you can confirm your endpoint is setup correctly.

Posting to a Controller Endpoint

To read from the [FromBody] attribute when posting data you need to create a class to map and resolve the JSON object being posted.

Create a class which maps to your payload:

public class Payload {
    public DateTime? date { get; set; }
}

The JSON object equivalent would look like:

{
    "date": ""
}

Remember to match instance variables case or it will not resolve.

Now we need to setup our HTTP client. You can use any HTTP package your prefer but for this example I will use axios:

Install axios using npm:

npm i axios

Import the axios library at the top of your class:

import axios from "axios";

Now build your JSON object and post to your endpoint:

//using shorthand
var payload = {
    date
};

await axios
    .post('https://localhost:3001/api/demo/date', payload)
        .then(function (response) {
            console.log(response);
        })

Notice I am using localhost:3001 this may be different depending on which port your project uses.

Convert UTC Date Format to Local Time (C#)

It is best to create a utility function that you can use in your project:

public static class Constants {

    public static DateTime GetLocalDate(DateTime date)
    {
        try
        {
            return (date.Kind != DateTimeKind.Local) ? TimeZoneInfo.ConvertTimeFromUtc(date, TimeZoneInfo.Local) : date;

        }
        catch (Exception)
        {
            return DateTime.Now;
        }
    }
}

This uses the DRY principal (Dont Repeat Yourself) and makes it easier to make updates down the road. It takes in a DateTime parameter and first checks its kind. If the date is not in local format it will proceed to convert the date from UTC to local date and time. This is needed because you are going to store DateTime values in the database in local time.

Now we can use the utility function above to complete the ConvertDate function:

[HttpPost("date")]
public IActionResult ConvertDate([FromBody] Payload payload)
{
    var date = Constants.GetLocalDate(payload.date.Value);
    return Ok(date);
}

Conclusion

By defining dates in UTC date format you will not run into formatting exceptions regardless where your end user resides or where your API is hosted. As an added benefit you can run reports and process data in your local time without extra processing or conversions. By defining GetLocalDate as a static function you can enforce the same conversion across your project and minimize the code debt.

You can find a full working example at: https://github.com/DanDev-Solutions-Inc/dates-reactjs-dot-net-5