Formatering av datum och tal i Bind-expression

(Bakgrund När jag gick trean på gymnasiet för åtta år sen gick jag en slags IT-inriktning. Kursen bestod mest av att göra Shockwave-prylar [som var stort då, tänk vad tiden går ;-)] och multimediaprojekt på CD-skiva... Men jag var mer intresserad av att göra hemsidor/webbaserat och fick godkänt att ägna mina lektioner åt att självstudera det som idag kallas för klassisk ASP. Mitt projekt blev en internweb åt skolan som jag efter studenten fick anställning på skolan för att verkligen dra igång på riktigt. Den används än idag och vidareutvecklas lite då och då. Efter höstens Asp.NET-kurs på min nuvarande KY-utbildning har jag förstås inte kunnat låta bli att börja fila på en Asp.NET-version av internwebben, som för övrigt går under namnet "Tick-Tack". Nu har jag kommit en bit på vägen och här på bloggen kommer jag under utvecklingens gång dela med mig av diverse Asp.NET-upptäckter som säkert kan komma till nytta även för andra.)

En av funktionerna i Tick-Tack är en anslagstavla dit samtliga användare kan posta inlägg. Följande ItemTemplate i en ListView-kontroll kommer att visa upp inläggen från anslagstavlan;

   <ItemTemplate>
       <div class="item">
           <div class="icon"><img src="../images/icon_board.png" /></div>
           <span class="credit">
               <asp:Label ID="authorNameLabel" runat="server" Text='<%# Bind("authorName") %>' />
               <br />
               <asp:Label ID="timeStampLabel" runat="server" Text='<%# Bind("timeStamp") %>' />
           </span>
           <br />
           <asp:Label ID="messageLabel" runat="server" Text='<%# Bind("message") %>' />
           <br />
           <asp:LinkButton ID="DeleteButton" runat="server" CausesValidation="False" CommandName="Delete" Text="Ta bort" />                               
       </div>
   </ItemTemplate>

ListView-kontrollen är kopplad till en SqlDataSource. Den hämtar poster där kolumnerna authorName, timeStamp och message finns med. När jag väl kommit så här långt fanns det tre saker jag ville fixa till;

  1. Möjlighet att formatera formatet på hur datumet, timeStamp, skrivs ut.
  2. Endast visa Ta bort-länken för administratörer.
  3. Länka namnet på inläggets författare till en annan sida som presenterar personen. Dessutom på ett generellt sätt så att det går att använda från andra listningar där namn skrivs ut på samtliga sidor i hela internwebsapplikationen.

I detta blogginlägg kommer jag att ta upp punkt ett, de övriga två i kommande blogginlägg. I exemplet ovan skrivs timeStamp ut i formatet 2008-06-19 11:39:00. Datatypen i databasen är en smalldatetime så sekundsiffrorna kommer alltid vara 00 och även om de hade varit nåt annat känns det ointressant att skriva ut sekundsiffrorna, timme och minut vill jag dock ha med. Efter lite googlande och sökande på msdn fann jag att Bind-uttrycket har ett andra valfritt argument som heter formatString. Den erbjuder en möjlighet att formatera datumet på samma sätt som man kan göra med string.Format-metoden;

Label1.Text = string.Format("Idag är det {0}", DateTime.Today);
//Ger utskrift: Idag är det 2008-06-19 00:00:00

Label2.Text = string.Format("Idag är det {0}", DateTime.Today.ToLongDateString());
//Ger utskrift: Idag är det den 19 juni 2008

Label3.Text = string.Format("Idag är det {0:D}", DateTime.Today);
//Ger samma utskrift som föregeånde: Idag är det den 19 juni 2008
        
Label4.Text = string.Format("Apelsinen kostade {0:C}", 5);
//Ger utskrift: Apelsinen kostade 5,00 kr

Label5.Text = string.Format("Det här är ett högt tal: {0:N}", 3247893289723324);
//Ger utskrift: Det här är ett högt tal: 3 247 893 289 723 324,00

string.Format är alltså en metod som först tar en sträng med x antal platshållare, {0} {1} etc, och därefter ytterligare ett argument för varje platshållare och returnerar en sträng där de efterföljande argumenten ersatt respektive platshållare. Men som du ser kan platshållarna göra mer än så, särskilt när det gäller datum och siffror. "D" är en standardformatsträng för "Long date pattern", vilket är samma datumformat som returnas av datetimeobjektets ToLongDateString-metod. Se MSDN:s förteckning över Standard Date and Time Format Strings. C står för Currency och N för Number och de är båda exempel på hur man kan manipulera tal-variabler via string.format. Se MSDN:s förteckning över Standard Numeric Format Strings. Så vad har nu allt detta att göra med utskriften av timeStamp i exemplet längst upp? Jo, som andra argument till Bind kan man alltså skicka in en formatString enligt följande;

<asp:Label ID="timeStampLabel" runat="server" Text='<%# Bind("timeStamp", "{0:D}") %>' />

Platshållare 0 kommer alltså ersättas av värdet i kolumnen timeStamp och utskriften kommer att formateras som ett "Long date pattern". Det var dock inte detta format jag ville ha i mitt sammanhang. Faktum är att det finns ingen standardformatsträng som erbjuder formatet hela datumet, men bara timmar och minuter i tiden. Då kan man använda sig av Custom Date and Time Format Strings. Här erbjuds en möjlighet att helt och hållet styra över hur datumet ska skrivas ut och den variant jag ville ha ser ut så här:

<asp:Label ID="timeStampLabel" runat="server" Text='<%# Bind("timeStamp", "{0:yyyy-MM-dd hh:mm}") %>' />

Fördelen med Standard-formaten är förstås att de tar hänsyn till aktuell kultur vilket är användbart om sajten du jobbar med är flerspråkig. Det skulle man kunna lösa genom att skriva ut två labels, en som får ta hand om datumdelen och en som får ta hand om tidsdelen;

<asp:Label ID="dateLabel" runat="server" Text='<%# Bind("timeStamp", "{0:d}") %>' />
<asp:Label ID="timeLabel" runat="server" Text='<%# Bind("timeStamp", "{0:t}") %>' />

Och eftersom man aldrig vet vad som händer i framtiden, blir det den lösningen jag kör.

No comments :

Post a Comment