119

If I have in my model class a property of type DateTime how can I render it in a specific format - for example in the format which ToLongDateString() returns?

I have tried this...

@Html.DisplayFor(modelItem => item.MyDateTime.ToLongDateString())

...which throws an exception because the expression must point to a property or field. And this...

@{var val = item.MyDateTime.ToLongDateString();
  Html.DisplayFor(modelItem => val);
}

...which doesn't throw an exception, but the rendered output is empty (although val contains the expected value, as I could see in the debugger).

Thanks for tips in advance!

Edit

ToLongDateString is only an example. What I actually want to use instead of ToLongDateString is a custom extension method of DateTime and DateTime?:

public static string FormatDateTimeHideMidNight(this DateTime dateTime)
{
    if (dateTime.TimeOfDay == TimeSpan.Zero)
        return dateTime.ToString("d");
    else
        return dateTime.ToString("g");
}

public static string FormatDateTimeHideMidNight(this DateTime? dateTime)
{
    if (dateTime.HasValue)
        return dateTime.Value.FormatDateTimeHideMidNight();
    else
        return "";
}

So, I think I cannot use the DisplayFormat attribute and DataFormatString parameter on the ViewModel properties.

Slauma
  • 175,098
  • 59
  • 401
  • 420

15 Answers15

176

You could decorate your view model property with the [DisplayFormat] attribute:

[DisplayFormat(DataFormatString = "{0:dd/MM/yyyy}", 
               ApplyFormatInEditMode = true)]
public DateTime MyDateTime { get; set; }

and in your view:

@Html.EditorFor(x => x.MyDate)

or, for displaying the value,

@Html.DisplayFor(x => x.MyDate)

Another possibility, which I don't recommend, is to use a weakly typed helper:

@Html.TextBox("MyDate", Model.MyDate.ToLongDateString())
R. Schreurs
  • 8,587
  • 5
  • 43
  • 62
Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • 1
    @Darin: I don't want an input element, but only static text output. I should also mention that the actual format is created by a custom extension method of `DateTime` (ToLongDateString was only an example), so it is unlikely that I can use `DataFormatString`. – Slauma May 14 '11 at 12:12
  • My aversion to this is that it loosely couples the presentation layer with the model. Sure the view can just ignore it and implement it's own format, but if you put that on there, you're probably not intending it to be ignored. – Nick Larsen May 14 '11 at 12:18
  • 2
    @Slauma, how about `@Html.DisplayFor(x => x.MyDateTime)`. @NickLarsen that's the reason why view models should be used. In my example I decorate the view model with this attribute and a view is already tied to a given view, that's its purpose. – Darin Dimitrov May 14 '11 at 12:43
  • @Darin: I think I cannot use `DisplayFor` together with the `DataFormatString` because, as I said in my comment, my format comes from a custom extension method. I've edited my question to make this clearer. – Slauma May 14 '11 at 12:59
  • 1
    @Slauma, OK, in this case you could either use a custom display template or have your view model use a string property and the conversion will be done at the mapping layer when you map between the model and the view model (this way you could still only use Html.DisplayFor in the view). – Darin Dimitrov May 14 '11 at 13:02
  • @DarinDimitrov: I also don't agree with putting any kind of display attribute on a view model. The view model should be able to drive multiple views, not a particular one that happens to use this format. – Nick Larsen May 14 '11 at 14:15
  • 5
    @NickLarsen, nope, it's one view model per view. It is because people make this mistake that questions like *How do I exclude some properties from validation in one controller action and not on other?* are so common on SO. – Darin Dimitrov May 14 '11 at 15:58
  • 1
    Coming back to this question a year later, I agree with the argument for one model per view. I still think anything dealing with the display choices belong in the view and not the model however. – Nick Larsen Apr 06 '12 at 13:59
  • @Darin: I tried to get the `DisplayFormat` attribute working on my ViewModel but instead of applying the `DataFormatString`, the `Html.DisplayFor()` renders the date in the `CurrentCulture` format! Is there a way to tweak this precedence? – Ε Г И І И О May 18 '12 at 15:53
  • {0:dd/MM/yyyy} looks not elegant, why they want to design in such way. – Timeless Jul 17 '14 at 10:03
  • Works for me, although if ToLongDateString is what was actually wanted then the DataFormatString should be "{0:D}". – Carl Sep 08 '15 at 08:49
161

If all you want to do is display the date with a specific format, just call:

@String.Format(myFormat, Model.MyDateTime)

Using @Html.DisplayFor(...) is just extra work unless you are specifying a template, or need to use something that is built on templates, like iterating an IEnumerable<T>. Creating a template is simple enough, and can provide a lot of flexibility too. Create a folder in your views folder for the current controller (or shared views folder) called DisplayTemplates. Inside that folder, add a partial view with the model type you want to build the template for. In this case I added /Views/Shared/DisplayTemplates and added a partial view called ShortDateTime.cshtml.

@model System.DateTime

@Model.ToShortDateString()

And now you can call that template with the following line:

@Html.DisplayFor(m => m.MyDateTime, "ShortDateTime")
Nick Larsen
  • 18,631
  • 6
  • 67
  • 96
  • Thanks, this looks good, and this template parameter ("ShortDateTime") solves also the problem I had described in my comment to ataddeini answer. – Slauma May 14 '11 at 13:01
  • 3
    If the type is "DateTime?" instead of "DateTime" (@model DateTime?)... the ciplay template will handle nullable or not nullable datetimes. The file's name should remain "DateTime.cshtml". – Romias Oct 02 '11 at 01:23
  • +1 Had to comment on this, worked great in my application! Thanks! – Russell Christensen Mar 26 '13 at 19:56
  • Use @Html.DisplayFor() is not extra work, it renders model's html representation, even without templates.... don't be confused... – Cabuxa.Mapache Mar 12 '14 at 07:36
  • http://stackoverflow.com/questions/19920603/date-format-using-html-displayfor-in-mvc5 contains code that is helpful in dealing with nullable datetimes @Romias mentions. – Walter de Jong Mar 07 '17 at 23:26
27

Simple formatted output inside of the model

@String.Format("{0:d}", model.CreatedOn)

or in the foreach loop

@String.Format("{0:d}", item.CreatedOn)
Christian Specht
  • 35,843
  • 15
  • 128
  • 182
odesuk
  • 1,197
  • 1
  • 12
  • 10
26

I use the following approach to inline format and display a date property from the model.

@Html.ValueFor(model => model.MyDateTime, "{0:dd/MM/yyyy}")

Otherwise when populating a TextBox or Editor you could do like @Darin suggested, decorated the attribute with a [DisplayFormat] attribute.

Steven
  • 1,444
  • 17
  • 23
9

If all your DateTime types are rendered the same way you can use a custom DateTime display template.

In your Views folder create a folder named "DisplayTemplates" either under your controller specific views folder, or under "Shared" folder (these work similar to partials).

Inside create a file named DateTime.cshtml that takes DateTime as the @model and code how you want to render your date:

@model System.DateTime
@Model.ToLongDateString()

Now you can just use this in your views and it should work:

@Html.DisplayFor(mod => mod.MyDateTime)

As long as you follow the convention of adding it to the "DisplayTemplates" folder and naming the file to match the type your are displaying, MVC will automatically use that to display your values. This also works for editing scenarios using "EditorTemplates".

Here's some more information on templates.

ataddeini
  • 4,931
  • 26
  • 34
  • Thanks, I just tested it and it works fine if the type is really `DateTime`. However I have a few nullable DateTime properties. I tried to create a second file in the `DisplayTemplates` folder, called `NullableDateTime.cshtml` and within: `@using MyHelpers @model System.DateTime? @Model.MyCustomExtension()` Here `MyCustomExtension` is an extension method on `DateTime?`. However it get an exception when a DateTime? field is really null telling me that the dictionary requires a model element of type `DateTime` which isn't null. Is there a way to define a DisplayTemplate for a nullable DateTime? – Slauma May 14 '11 at 12:39
  • @Slauma: Hmm, good question. I would probably stick with the `NullableDateTime.cshtml` and use the approach that @NickLarsen suggested and use `@Html.DisplayFor(m => m.MyDateTime, "NullableDateTime")`. – ataddeini May 14 '11 at 17:10
  • You don't need to explicitly add the name of the template if your DateTime.cshtml template is set as "@model DateTime?" instead of "DateTime". That way all the Dates (nullable or not) are handled by the same template... – Romias Oct 02 '11 at 01:57
8

My preference is to keep the formatting details with the view and not the viewmodel. So in MVC4/Razor:

@Html.TextBoxFor(model => model.DateTime, "{0:d}");

datetime format reference: http://msdn.microsoft.com/en-us/library/az4se3k1(v=vs.71).aspx

Then I have a JQuery datepicker bound to it, and that put's the date in as a different format...doh!

Looks like I need to set the datepicker's format to the same formatting.

So I'm storing the System.Globalization formatting in a data-* attribute and collecting it when setting up the

@Html.TextBoxFor(
    model => model.DateTime.Date, 
    "{0:d}", 
    new 
    { 
        @class = "datePicker", 
        @data_date_format=System.Globalization.CultureInfo
                          .CurrentUICulture.DateTimeFormat.ShortDatePattern 
    }));

And here's the sucky part: the formats of .net and datepicker do not match, so hackery is needed:

$('.datePicker').each(function(){
    $(this).datepicker({
        dateFormat:$(this).data("dateFormat").toLowerCase().replace("yyyy","yy")
    });
});

that's kind of weak, but should cover a lot of cases.

SteveC
  • 15,808
  • 23
  • 102
  • 173
philn5d
  • 636
  • 7
  • 12
2

works for me

<%=Model.MyDateTime.ToString("dd-MMM-yyyy")%>
numerah
  • 498
  • 7
  • 29
2

Had the same problem recently.

I discovered that simply defining DataType as Date in the model works as well (using Code First approach)

[DataType(DataType.Date)]
public DateTime Added { get; set; }
1

In MVC5 I'd use, if your model is the datetime

string dt = Model.ToString("dd/MM/yyy"); 

Or if your model contains the property of the datetime

string dt = Model.dateinModel.ToString("dd/MM/yyy"); 

Here's the official meaning of the Formats:

https://msdn.microsoft.com/en-us/library/8kb3ddd4(v=vs.110).aspx

Jose Ortega
  • 1,002
  • 13
  • 23
1

you can do like this @item.Date.Value.Tostring("dd-MMM-yy");

Saurabh Solanki
  • 2,146
  • 18
  • 31
0

if I just want to display the date in short format I just use @Model.date.ToShortDateString() and it prints the date in

Marcianin
  • 461
  • 3
  • 8
0

If all you want to do is display the date with a specific format, just call:

@Model.LeadDate.ToString("dd-MMM-yyyy")

@Model.LeadDate.ToString("MM/dd/yy")

It will result in following format,

26-Apr-2013

04/26/13
Kailas Mane
  • 1,877
  • 1
  • 15
  • 12
0

this will display in dd/MM/yyyy format in your View

In View:

instead of DisplayFor use this code

<td>

@(item.Startdate.HasValue ? item.Startdate.Value.ToString("dd/MM/yyyy") : "Date is Empty")

</td

it also checks if the value is null in date column, if true then it will display Date is Empty or the actual formatted date from the column.

Hope helps someone.

Shaiju T
  • 6,201
  • 20
  • 104
  • 196
0
@{
  string datein = Convert.ToDateTime(item.InDate).ToString("dd/MM/yyyy");        
  @datein
}
Tunaki
  • 132,869
  • 46
  • 340
  • 423
wesley7
  • 101
  • 3
-2

Only View File Adjust like this. You may try this.

@Html.FormatValue( (object)Convert.ChangeType(item.transdate, typeof(object)), 
                            "{0: yyyy-MM-dd}")

item.transdate it is your DateTime type data.

SteveC
  • 15,808
  • 23
  • 102
  • 173