¿Cómo representar un DateTime en un formato específico en ASP.NET MVC 3?

117

Si tengo en mi clase de modelo una propiedad de tipo, DateTime¿cómo puedo representarla en un formato específico, por ejemplo, en el formato que ToLongDateString()devuelve?

He probado esto ...

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

... que genera una excepción porque la expresión debe apuntar a una propiedad o campo. Y esto...

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

... que no lanza una excepción, pero la salida renderizada está vacía (aunque valcontiene el valor esperado, como pude ver en el depurador).

¡Gracias por los consejos de antemano!

Editar

ToLongDateStringes solo un ejemplo. Lo que realmente quiero usar en lugar de ToLongDateStringes un método de extensión personalizado de DateTimey 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 "";
}

Entonces, creo que no puedo usar el DisplayFormatatributo y el DataFormatStringparámetro en las propiedades de ViewModel.

Slauma
fuente

Respuestas:

159

Si todo lo que desea hacer es mostrar la fecha con un formato específico, simplemente llame a:

@String.Format(myFormat, Model.MyDateTime)

Usar @Html.DisplayFor(...)es solo un trabajo adicional a menos que esté especificando una plantilla, o necesite usar algo que esté construido sobre plantillas, como iterar un archivo IEnumerable<T>. Crear una plantilla es bastante simple y también puede proporcionar mucha flexibilidad. Cree una carpeta en su carpeta de vistas para el controlador actual (o carpeta de vistas compartidas) llamado DisplayTemplates. Dentro de esa carpeta, agregue una vista parcial con el tipo de modelo para el que desea construir la plantilla. En este caso agregué /Views/Shared/DisplayTemplatesy agregué una vista parcial llamada ShortDateTime.cshtml.

@model System.DateTime

@Model.ToShortDateString()

Y ahora puedes llamar a esa plantilla con la siguiente línea:

@Html.DisplayFor(m => m.MyDateTime, "ShortDateTime")
Nick Larsen
fuente
Gracias, esto se ve bien, y este parámetro de plantilla ("ShortDateTime") también resuelve el problema que describí en mi comentario a la respuesta de ataddeini.
Slauma
3
Si el tipo es "DateTime?" en lugar de "DateTime" (@model DateTime?) ... la plantilla ciplay manejará las fechas y horas que aceptan valores NULL o no. El nombre del archivo debe seguir siendo "DateTime.cshtml".
Romias
+1 Tuve que comentar sobre esto, ¡funcionó muy bien en mi aplicación! ¡Gracias!
Russell Christensen
Usar @ Html.DisplayFor () no es un trabajo adicional, representa la representación html del modelo, incluso sin plantillas ... no se confunda ...
Cabuxa.Mapache
stackoverflow.com/questions/19920603/… contiene código que es útil para lidiar con las menciones de @Romias datetimes que aceptan valores NULL.
Walter de Jong
171

Puede decorar la propiedad de su modelo de vista con el [DisplayFormat]atributo:

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

y en tu opinión:

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

o, para mostrar el valor,

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

Otra posibilidad, que no recomiendo, es utilizar un ayudante de tipo débil:

@Html.TextBox("MyDate", Model.MyDate.ToLongDateString())
Darin Dimitrov
fuente
1
@Darin: No quiero un elemento de entrada, sino solo una salida de texto estático. También debo mencionar que el formato real se crea mediante un método de extensión personalizado de DateTime(ToLongDateString fue solo un ejemplo), por lo que es poco probable que pueda usar DataFormatString.
Slauma
2
@Slauma, ¿qué tal @Html.DisplayFor(x => x.MyDateTime)? @NickLarsen, esa es la razón por la que se deben usar modelos de vista. En mi ejemplo, decoro el modelo de vista con este atributo y una vista ya está vinculada a una vista determinada, ese es su propósito.
Darin Dimitrov
1
@Slauma, OK, en este caso puede usar una plantilla de visualización personalizada o hacer que su modelo de vista use una propiedad de cadena y la conversión se realizará en la capa de mapeo cuando mapee entre el modelo y el modelo de vista (de esta manera podría todavía solo use Html.DisplayFor en la vista).
Darin Dimitrov
5
@NickLarsen, no, es un modelo de vista por vista. Es porque la gente comete este error que preguntas como ¿Cómo excluyo algunas propiedades de la validación en una acción del controlador y no en otra? son tan comunes en SO.
Darin Dimitrov
1
Volviendo a esta pregunta un año después, estoy de acuerdo con el argumento de un modelo por vista. Sin embargo, sigo pensando que todo lo relacionado con las opciones de visualización pertenece a la vista y no al modelo.
Nick Larsen
26

Salida con formato simple dentro del modelo

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

o en el bucle foreach

@String.Format("{0:d}", item.CreatedOn)
Odesuk
fuente
Parece un duplicado de la respuesta aceptada de usarstring.Format
Paul Tyng
2
@PaulTyng esta respuesta fue más clara para mí que la respuesta aceptada, odesuk en realidad mostró el formato en el primer parámetro que, como nuevo, me ayuda.
Dan Beaulieu
1
Estoy de acuerdo, esta es la respuesta que me ayudó.
Glenn Garson
26

Utilizo el siguiente enfoque para formatear en línea y mostrar una propiedad de fecha del modelo.

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

De lo contrario, al completar un TextBox o Editor, podría hacer como sugirió @Darin, decorar el atributo con un [DisplayFormat]atributo.

Steven
fuente
¡Esta es la solución que estoy buscando!
Envil
¡Esta es la solución que estaba buscando!
Raihan Ridoy
9

Si todos sus DateTimetipos se representan de la misma manera, puede usar una DateTimeplantilla de visualización personalizada .

En su carpeta Vistas, cree una carpeta llamada "DisplayTemplates", ya sea en la carpeta de vistas específicas de su controlador o en la carpeta "Compartida" (funcionan de manera similar a las parciales).

En el interior, cree un archivo llamado DateTime.cshtmlque toma DateTimecomo @modelcódigo y cómo desea representar su fecha:

@model System.DateTime
@Model.ToLongDateString()

Ahora puede usar esto en sus vistas y debería funcionar:

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

Siempre que siga la convención de agregarlo a la carpeta "DisplayTemplates" y nombrar el archivo para que coincida con el tipo que está mostrando, MVC lo usará automáticamente para mostrar sus valores. Esto también funciona para editar escenarios usando "EditorTemplates".

Aquí hay más información sobre las plantillas .

ataddeini
fuente
Gracias, acabo de probarlo y funciona bien si el tipo es realmente DateTime. Sin embargo, tengo algunas propiedades DateTime que aceptan valores NULL. Intenté crear un segundo archivo en la DisplayTemplatescarpeta, llamado NullableDateTime.cshtmly dentro: @using MyHelpers @model System.DateTime? @Model.MyCustomExtension()Aquí MyCustomExtensionhay un método de extensión en DateTime?. Sin embargo, ¿obtiene una excepción cuando un DateTime? El campo es realmente nulo y me dice que el diccionario requiere un elemento de modelo de tipo DateTimeque no es nulo. ¿Hay alguna forma de definir un DisplayTemplate para un DateTime anulable?
Slauma
@Slauma: Hmm, buena pregunta. Probablemente me quedaría con NullableDateTime.cshtmly usaría el enfoque que @NickLarsen sugirió y usaría @Html.DisplayFor(m => m.MyDateTime, "NullableDateTime").
ataddeini
No es necesario que agregue explícitamente el nombre de la plantilla si su plantilla DateTime.cshtml está configurada como "@model DateTime?" en lugar de "DateTime". De esa manera, todas las fechas (anulables o no) se manejan con la misma plantilla ...
Romias
7

Mi preferencia es mantener los detalles de formato con la vista y no con el modelo de vista. Entonces en MVC4 / Razor:

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

Referencia de formato de fecha y hora: http://msdn.microsoft.com/en-us/library/az4se3k1(v=vs.71).aspx

Luego tengo un selector de fecha JQuery vinculado a él, y eso pone la fecha en un formato diferente ... ¡doh!

Parece que necesito configurar el formato del selector de fechas con el mismo formato.

Así que estoy almacenando el System.Globalizationformato en un atributo data- * y lo recopilo al configurar el

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

Y aquí está la parte desagradable: los formatos de .net y datepicker no coinciden, por lo que se necesita piratería:

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

eso es un poco débil, pero debería cubrir muchos casos.

philn5d
fuente
Las primeras 3 líneas son las más importantes :) Ejemplo y enlace a la definición de formato
Borik
2

funciona para mi

<%=Model.MyDateTime.ToString("dd-MMM-yyyy")%>
numerah
fuente
Obviamente, esta pregunta está utilizando el motor de vista de afeitar, ha respondido en un idioma diferente.
Rhys Bevilaqua
2

Recientemente tuve el mismo problema.

Descubrí que simplemente definir DataType como Date en el modelo también funciona (usando el enfoque Code First)

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

puedes hacer así @item.Date.Value.Tostring("dd-MMM-yy");

Saurabh Solanki
fuente
0

si solo quiero mostrar la fecha en formato corto, solo uso @ Model.date.ToShortDateString () e imprime la fecha en

Marcianin
fuente
0

Si todo lo que desea hacer es mostrar la fecha con un formato específico, simplemente llame a:

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

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

Dará como resultado el siguiente formato,

26-Apr-2013

04/26/13
Melena de Kailas
fuente
¿Qué pasará si @ Model.LeadDate == null?
Bimal Das
0

esto se mostrará en dd/MM/yyyyformato en su Vista

En vista:

en lugar de DisplayForusar este código

<td>

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

</td

también verifica si el valor es nulo en la columna de fecha, si es verdadero, mostrará la fecha está vacía o la fecha formateada real de la columna.

La esperanza ayuda a alguien.

shaijut
fuente
0
@{
  string datein = Convert.ToDateTime(item.InDate).ToString("dd/MM/yyyy");        
  @datein
}
Wesley7
fuente
-2

Ver solo ajuste de archivo como este. Puedes probar esto.

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

item.transdateson sus DateTimedatos de tipo.

Martine Chang
fuente