Como renderizar um DateTime em um formato específico na ASP.NET MVC 3?

117

Se eu tiver em minha classe de modelo uma propriedade do tipo, DateTimecomo posso renderizá-la em um formato específico - por exemplo, no formato que ToLongDateString()retorna?

Eu tentei isso ...

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

... que lança uma exceção porque a expressão deve apontar para uma propriedade ou campo. E isto...

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

... que não lança uma exceção, mas a saída renderizada está vazia (embora valcontenha o valor esperado, como pude ver no depurador).

Obrigado por dicas com antecedência!

Editar

ToLongDateStringé apenas um exemplo. O que eu realmente quero usar em vez de ToLongDateStringé um método de extensão personalizado de DateTimee 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 "";
}

Portanto, acho que não posso usar o DisplayFormatatributo e o DataFormatStringparâmetro nas propriedades de ViewModel.

Slauma
fonte

Respostas:

159

Se tudo o que você deseja fazer é mostrar a data com um formato específico, basta ligar:

@String.Format(myFormat, Model.MyDateTime)

Usar @Html.DisplayFor(...)é apenas um trabalho extra, a menos que você esteja especificando um modelo ou precise usar algo que seja construído em modelos, como iterar um IEnumerable<T>. A criação de um modelo é bastante simples e pode fornecer muita flexibilidade também. Crie uma pasta em sua pasta de visualizações para o controlador atual (ou pasta de visualizações compartilhadas) chamada DisplayTemplates. Dentro dessa pasta, adicione uma vista parcial com o tipo de modelo para o qual deseja construir o modelo. Neste caso, adicionei /Views/Shared/DisplayTemplatese adicionei uma visão parcial chamada ShortDateTime.cshtml.

@model System.DateTime

@Model.ToShortDateString()

E agora você pode chamar esse modelo com a seguinte linha:

@Html.DisplayFor(m => m.MyDateTime, "ShortDateTime")
Nick Larsen
fonte
Obrigado, isso parece bom e este parâmetro de modelo ("ShortDateTime") também resolve o problema que eu descrevi em meu comentário à resposta de ataddeini.
Slauma
3
Se o tipo for "DateTime?" em vez de "DateTime" (@model DateTime?) ... o modelo ciplay tratará datetimes anuláveis ​​ou não anuláveis. O nome do arquivo deve permanecer "DateTime.cshtml".
Romias,
Tive que comentar sobre isso, funcionou muito bem no meu aplicativo! Obrigado!
Russell Christensen
Usar @ Html.DisplayFor () não é um trabalho extra, ele renderiza a representação html do modelo, mesmo sem modelos .... não se confunda ...
Cabuxa.Mapache
stackoverflow.com/questions/19920603/… contém código que é útil para lidar com datetimes anuláveis ​​que @Romias menciona.
Walter de Jong
171

Você pode decorar a propriedade do seu modelo de visualização com o [DisplayFormat]atributo:

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

e na sua opinião:

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

ou, para exibir o valor,

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

Outra possibilidade, que não recomendo, é usar um auxiliar de digitação fraca:

@Html.TextBox("MyDate", Model.MyDate.ToLongDateString())
Darin Dimitrov
fonte
1
@Darin: Não quero um elemento de entrada, mas apenas saída de texto estático. Devo também mencionar que o formato real é criado por um método de extensão personalizado de DateTime(ToLongDateString foi apenas um exemplo), portanto, é improvável que eu possa usar DataFormatString.
Slauma
2
@Slauma, que tal @Html.DisplayFor(x => x.MyDateTime). @NickLarsen é a razão pela qual os modelos de visualização devem ser usados. No meu exemplo, eu decoro o modelo de visualização com este atributo e uma visualização já está ligada a uma determinada visualização, esse é o seu propósito.
Darin Dimitrov
1
@Slauma, OK, neste caso você pode usar um modelo de exibição personalizado ou fazer com que seu modelo de exibição use uma propriedade de string e a conversão será feita na camada de mapeamento quando você mapear entre o modelo e o modelo de exibição (desta forma, você pode ainda use apenas Html.DisplayFor na visualização).
Darin Dimitrov
5
@NickLarsen, não, é um modelo de visualização por visualização. É porque as pessoas cometem esse erro que perguntas como Como excluo algumas propriedades da validação em uma ação do controlador e não em outra? são tão comuns no SO.
Darin Dimitrov
1
Voltando a essa questão um ano depois, concordo com o argumento de um modelo por visualização. Eu ainda acho que qualquer coisa relacionada às opções de exibição pertence à visualização e não ao modelo.
Nick Larsen
26

Saída formatada simples dentro do modelo

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

ou no loop foreach

@String.Format("{0:d}", item.CreatedOn)
odesuk
fonte
Parece ser uma duplicata da resposta aceita de usostring.Format
Paul Tyng
2
@PaulTyng esta resposta foi mais clara para mim do que a resposta aceita, odesuk realmente mostrou o formato no primeiro parâmetro que, como newb, me ajuda.
Dan Beaulieu
1
Eu concordo, essa é a resposta que me ajudou.
glenn garson
26

Eu uso a seguinte abordagem para o formato embutido e exibo uma propriedade de data do modelo.

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

Caso contrário, ao preencher um TextBox ou Editor você poderia fazer como @Darin sugeriu, decorar o atributo com um [DisplayFormat]atributo.

Steven
fonte
Esta é a solução que procuro!
Envil,
Esta é a solução que procurava!
Raihan Ridoy
9

Se todos os seus DateTimetipos forem renderizados da mesma maneira, você pode usar um DateTimemodelo de exibição personalizado .

Na pasta Views, crie uma pasta chamada "DisplayTemplates" na pasta views específicas do controlador ou na pasta "Compartilhada" (funcionam de maneira semelhante às parciais).

Dentro, crie um arquivo chamado DateTime.cshtmlque assume DateTimecomo o @modelcódigo e como você deseja renderizar sua data:

@model System.DateTime
@Model.ToLongDateString()

Agora você pode apenas usar isso em suas visualizações e deve funcionar:

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

Contanto que você siga a convenção de adicioná-lo à pasta "DisplayTemplates" e nomear o arquivo para corresponder ao tipo que você está exibindo, o MVC usará isso automaticamente para exibir seus valores. Isso também funciona para editar cenários usando "EditorTemplates".

Aqui estão mais algumas informações sobre modelos .

Ataddeini
fonte
Obrigado, acabei de testá-lo e funciona bem se o tipo for realmente DateTime. No entanto, tenho algumas propriedades DateTime anuláveis. Tentei criar um segundo arquivo na DisplayTemplatespasta, chamado NullableDateTime.cshtmle dentro: @using MyHelpers @model System.DateTime? @Model.MyCustomExtension()Aqui MyCustomExtensionestá um método de extensão em DateTime?. No entanto, obtém uma exceção quando um DateTime? campo é realmente nulo, informando que o dicionário requer um elemento de modelo do tipo DateTimeque não é nulo. Existe uma maneira de definir um DisplayTemplate para um DateTime anulável?
Slauma de
@Slauma: Hmm, boa pergunta. Eu provavelmente continuaria com o NullableDateTime.cshtmle usaria a abordagem que @NickLarsen sugeriu e usaria @Html.DisplayFor(m => m.MyDateTime, "NullableDateTime").
ataddeini
Você não precisa adicionar explicitamente o nome do modelo se o seu modelo DateTime.cshtml estiver definido como "@model DateTime?" em vez de "DateTime". Dessa forma, todas as datas (anuláveis ​​ou não) são tratadas pelo mesmo modelo ...
Romias
7

Minha preferência é manter os detalhes de formatação com a visão e não com o modelo. Então, em MVC4 / Razor:

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

referência de formato datetime: http://msdn.microsoft.com/en-us/library/az4se3k1(v=vs.71).aspx

Então eu tenho um selecionador de data JQuery vinculado a ele, e que coloca a data em um formato diferente ... doh!

Parece que preciso definir o formato do selecionador de data com a mesma formatação.

Portanto, estou armazenando a System.Globalizationformatação em um atributo data- * e coletando-o ao configurar o

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

E aqui está a parte ruim: os formatos de .net e datepicker não combinam, então hackery é necessário:

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

isso é meio fraco, mas deve abranger muitos casos.

philn5d
fonte
As primeiras 3 linhas são as mais importantes :) Exemplo e link para definição de formato
Borik
2

funciona para mim

<%=Model.MyDateTime.ToString("dd-MMM-yyyy")%>
numerah
fonte
Obviamente, esta pergunta está usando o mecanismo de visualização de navalha. Você respondeu usando um idioma diferente.
Rhys Bevilaqua
2

Tive o mesmo problema recentemente.

Eu descobri que simplesmente definir DataType como Date no modelo também funciona (usando a abordagem Code First)

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

você pode fazer assim @item.Date.Value.Tostring("dd-MMM-yy");

Saurabh Solanki
fonte
0

se eu apenas quiser exibir a data em formato curto, eu apenas uso @ Model.date.ToShortDateString () e ele imprime a data em

Marcianin
fonte
0

Se tudo o que você deseja fazer é mostrar a data com um formato específico, basta ligar:

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

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

Isso resultará no seguinte formato,

26-Apr-2013

04/26/13
Kailas Mane
fonte
O que acontecerá se @ Model.LeadDate == null?
Bimal Das
0

isso será exibido em dd/MM/yyyyformato em sua Visualização

Em vista:

em vez de DisplayForusar este código

<td>

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

</td

ele também verifica se o valor é nulo na coluna de data; se for verdadeiro, ele exibirá Date is Empty ou a data real formatada da coluna.

A esperança ajuda alguém.

shaijut
fonte
0
@{
  string datein = Convert.ToDateTime(item.InDate).ToString("dd/MM/yyyy");        
  @datein
}
wesley7
fonte
0

Em MVC5 eu usaria, se o seu modelo é o datetime

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

Ou se o seu modelo contém a propriedade da data e hora

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

Aqui está o significado oficial dos formatos:

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

Jose Ortega
fonte
-2

Apenas Visualizar Arquivo Ajustar assim. Você pode tentar isso.

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

item.transdatesão seus DateTimedados de tipo.

Martine Chang
fonte