This post was most recently updated on July 7th, 2022.
7 min read.Have you ever struggled to make your ASP.NET MVC views format your properties of type DateTime correctly? I have. And I’ve been shot in the leg by weird hacks made by both myself (just 6 months earlier) and someone else. .NET Date/DateTime formatting is an endless bag of funsies in general.
So I thought I’d finally document the different ways one can set up the formatting of DateTime fields in ASP.NET Core projects specifically. Or at least all the ways I’ve found so far! :)
While this guide was originally written for traditional ASP.NET MVC, I’ve updated the article so that the concepts and the general order of things apply to ASP.NET Core DateTime formatting as well. Furthermore, a lot of the different methods and layers also apply to DateTime formats in any .NET application. And of course, there’s a bunch of tips for date formatting very specific to Entity Framework and even Microsoft SQL Server as well, so you should get some valuable tidbits of info for that tech as well!
Note: This guide does not describe localization on the whole. That’s a wider topic and a source of an endless number of interesting issues :) In this post I only delve into date formatting, mostly using TextBox as an example, as it seems to be at the same time the most used component, but also fairly tricky to get right.
Let’s try and figure this out!
All of the different ways I’ve found to affect the date format of a DateTime field in .NET
This is the order in which you can set (or mess) up the formatting, starting from the lowest level (database) and ending on the client-side.
I’ve found that for most cases, option 5 (Data Annotations to Model/ViewModel classes) is going to be the best way to go – but even then you need to be aware of the other options, as you (or whoever else working on the same project) can still mess up the formatting on other levels :)
Time needed: 30 minutes
How to format DateTimes in ASP.NET Core?
- Establish a convention and save your dates as preformatted strings already in the database
Storing your dates as text/varchar/similar data type in the database and just sticking to the right format from the get-go is an option. Kind of.
Yes – people really do that. It’s a bad idea, to begin with, but even worse if you’re not consistent with the formats of your stored dates.
Don’t do this. Instead, use the datetime column type. - Set the column in the database to a certain flavor of DateTime
Uh-oh – so just simply using ‘DateTime’ doesn’t save us entirely? Well, it almost does. There are different date/time formats you can use for your “DateTime-ish” columns.
This will come into effect if there’s nothing else that affects the format. Usually, there is, though, beginning from Entity Framework using DateTime type to store these values.
Source: https://docs.microsoft.com/en-us/sql/t–sql/data-types/datetime-transact-sql?view=sql-server-2017 - Set up the culture of your service
This is probably the “lowest” level of formatting in your actual application. It’s the easiest way to set your DateTime format pretty much everywhere in your application at once.
Setting the culture of the thread your application runs in either in the startup (Configure() in Startup.cs in .NET Core, or Application_Start() in Global.asax.cs in .NET), or in the web.config. - Set the culture of your application in the Application_Start
namespace …
{
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
Thread.CurrentThread.CurrentCulture = new
System.Globalization.CultureInfo("fi-FI");
}
}
}
Not too complicated! See below for an alternative approach: - Set the culture of your application in the web.config
<system.web>
<globalization uiculture="fi" culture="fi"></globalization>
</system.web> - Set the culture of your application in Startup.cs
services.Configure<RequestLocalizationOptions>(options =>
{var supportedCultures = new[] { new CultureInfo("en"), new
CultureInfo("fi")
} ;
options.DefaultRequestCulture = new RequestCulture("en", "en");
options.SupportedCultures = supportedCultures;
options.SupportedUICultures = supportedCultures;
} ) ; - Set up the culture of your page
In ASP.NET MVC, you can override the culture setting of your whole service or application on a page-to-page basis, if you so desire. The example below shows how to do that!
<%@ Page UICulture="fi" Culture="fi" %>
- Add Data Annotations to your EF Model’s classes
For situations when you don’t have to support multiple locales, I think this approach is my favorite. And it should work for pretty much any .NET application, as long as you’re using Entity Framework!
You can specify the format per field, per class, in your model, and unless something else is specified on the latter levels, they’ll be used on any views for that particular class. Neat, effective, but granular enough for most uses.
There are multiple ways that you can try and annotate the format directly on your model.
Note, however, that if you’re using automatically generated Model classes (this is the case if your project is database-first, for example), your changes will be overwritten when you next (auto-) update the Model. If this sentence rings no bells and you have no idea what I’m talking about, just check out your .cs -files for your Model classes for something like this at the beginning of the file. This particular warning has been added by EF.
A warning for auto-generated code in Visual Studio ASP.NET MVC Model class
If there’s a comment like that in your classes, it means you should not modify them. They’ll be overwritten if you ever need to recreate them from the database.
In this case, you need to use ViewModels for the annotations.
Using ViewModels instead of Models might be a good idea just in general. Why? They kind of offer you a new level between the Model and View – to offer a dedicated place for some simple logic and formatting, or to add new fields that don’t actually go to the database (but are rather used for calculated values) instead of cluttering the Model or Controller (or, heavens forbid, the VIEW) with this code. - Add a display format
Example:
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = “{0:yyyy/MM/dd}”]
public DateTime YourDate { get; set; }
If you want to avoid splitting your date formatting (or whatever else) logic in a million places, you could set the value of DataFormatString to a constant, and use the same value globally.
Alternatively, you would like to override the underlying DataType in the model directly. (See the below step on how to do this) - Override the underlying DataType in the model directly
Okay – a slightly different approach. This way you’ll be able to force the formatting of this DateTime object to be just Date. It’ll still be formatted based on other matters, but it’ll be formatted as a Date, not DateTime.
[DataType(DataType.Date)]
public DateTime YourDate { get; set; }
However, if you need to support multiple locales (or multiple date formats) for this particular property, this approach is not optimal. See below for more options! - Insert the date format on the view directly
Are you using the “TextBoxFor()” -method? If you are, you might find that your formats from the model classes are not applied. Weirdly enough, the TextBoxFor is an odd bird and doesn’t adhere to the same format specified for DateTime that other methods seem to work fine with.
For Html.TextBoxFor() -calls the Data Annotations won’t do the trick. This method doesn’t care about the format specified via data annotations at all.
In these cases, you can still set the format in the function call directly. The method below is available for MVC4+, so it should work for any current MVC project.Html.TextBoxFor(m => m.YourDate, "{0:d MMM yyyy}")
// You can even add additional classes in an overloaded call: Html.TextBoxFor(m =>
m.YourDate, "{0:MM/dd/yyyy}", new { @id="datepicker" })
Or with the following notation:@Html.TextBoxFor(m => m.YourDate, "{0:MM/dd/yyyy}")
- Format the DateTime type’s View directly
I’ll readily admit it – this is kind of a tricky one. I’m not sure if I would recommend this almost ever.
For a while, I really hated the developer who did this, but after a bit of consideration, I switched to good old self-loathing instead, since I spent about an hour changing the formatting at all different levels, before realizing they had decided to override it at the View for DateTime directly.
Why? Probably they had run into issues with formatting, and just decided to brute-force their way out of it. And it worked just fine, until they decided to change the format later, and forgot to change this override, too. And then left the company. And I was asked to take over.
Fun times. So, see below how to do this:@model DateTime?
@using your.namespace;
@if (Model.HasValue)
{
// This'll get you a fairly American date format
@Convert.ToDateTime(Model).ToString("MM/dd/yyyy}")
}
Avoid doing this majority of the time.
And for the record, I’m not talking about just using the American time format, although arguably that’s a bad idea as well…
But hardcoding the format in a view overriding the default for DateTime (or any other out-of-the-box type for that matter) is probably confusing, and you’re approaching your issue from the wrong direction. There’s probably an easier way around your problem. - JavaScript plug-ins and libraries
Okay – this is such a wide and complicated topic, that it’d probably be worth multiple blog articles on its own.
I’m only going to mention the possibility, that the format of your DateTime fields might be overridden by JavaScript finally when displaying them. This might be tricky to figure out. While there are a lot of possibilities on how to do this (and equally many ways to mess up), I’m mentioning a couple of examples:// With jQuery UI DatePicker
$("#yourField").datepicker("option", "dateFormat", "mm/dd/yy");
// or another way to do this:
$("#yourField1").datepicker({ dateFormat: 'mm/dd/yy' });
$("#yourField2").datepicker({ dateFormat: 'yy-mm-dd' });
<!-- Another example with BeatPicker library -->
<link rel="stylesheet" href="css/BeatPicker.css">
<script src="js/jquery-2.1.0.min.js"></script>
<script src="js/BeatPicker.js"></script>
<input type="text" data-beatpicker="true" data-beatpicker-position="['right','*']" data-beatpicker-format="['DD','MM','YYYY'],separator:'/'">
You might want to search through your code for any JavaScript libraries that affect your date formats. A good idea might be to search for the format that you’re seeing, not for any certain libraries – especially, if you inherited the codebase from someone else, and have no idea which libraries they have chosen to use! - Browser settings (by the user or even Group Policies)
Okay – this should be the last level of torment in this particular flavor of Inferno. We’re approaching the end of this rabbit hole.
Like so many other things, Group Policies can affect the date format shown to the end-user in your web application.
You can set the desired date format by setting the regional settings using Group Policies. This is a classic problem for Internet Explorer, but you can apply the policies to Google Chrome, too:
https://community.spiceworks.com/topic/595935-change-date-format-using-gpo
Although that appears to be pretty inconsistent (generally, just making it more complicated):
https://community.spiceworks.com/topic/264245-set-default-google-chrome-locale-using-group-policy
I don’t think this is done very often, but at the same time you might still run into this – some organizations absolutely love Group Policies. In my career, I’ve only run into this once.
Afterwords
This article described all of the different ways that I have found that affect the formatting of ASP.NET MVC DateTime fields. There’s probably more, and I’ll update them as soon as I run into them :)
Have you found another way? Share it with me in the comments below!
References
These are the sources I went through:
- https://stackoverflow.com/questions/16697872/why-is-displayformat-dataformatstring-not-working
- https://stackoverflow.com/questions/1961114/date-only-from-textboxfor
- https://stackoverflow.com/questions/1328025/jquery-ui-datepicker-change-date-format
- https://www.jerriepelser.com/blog/setting-thread-culture-aspnet5/
- https://documentation.devexpress.com/AspNet/12062/Localization/How-to-Set-a-Culture-for-an-ASP-NET-Web-Page
- https://www.devexpress.com/Support/Center/Question/Details/T108044/best-practices-to-change-the-current-culture-in-asp-net-mvc-application-using-combobox
- https://afana.me/archive/2011/01/14/aspnet-mvc-internationalization.aspx/
- Here are the different date/time formats you can use for your “DateTime-ish” columns:
Data type | Output |
---|---|
time | 12:35:29.1234567 |
date | 2017-05-08 |
smalldatetime | 2017-05-08 12:35:00 |
datetime | 2017-05-08 12:35:29.123 |
datetime2 | 2017-05-08 12:35:29.1234567 |
datetimeoffset | 2017-05-08 12:35:29.1234567 +12:15 |
- How to stop Surface Headphones from autoplaying audio when you place them on the desk? - December 10, 2024
- “Phone Link” permanently disabled and Windows claiming “Some of these settings are managed by your organization”? (Probably) an easy fix! - December 3, 2024
- Refreshing DefaultAzureCredential in Visual Studio - November 26, 2024