Ottieni AM / PM per una data e ora in minuscolo utilizzando solo un formato datetime
-
20-08-2019 - |
Domanda
Devo ottenere un formato DateTime personalizzato che includa il designatore AM / PM, ma voglio il " AM " oppure " PM " essere in minuscolo senza il resto dei caratteri in minuscolo.
È possibile usare un unico formato e senza usare una regex?
Ecco quello che ho in questo momento:
item.PostedOn.ToString("dddd, MMMM d, yyyy a\\t h:mmtt")
Un esempio dell'output in questo momento sarebbe sabato 31 gennaio 2009 alle 13:34
Soluzione
Lo formatterei personalmente in due parti: la parte non am / pm e la parte am / pm con ToLower:
string formatted = item.PostedOn.ToString("dddd, MMMM d, yyyy a\\t h:mm") +
item.PostedOn.ToString("tt").ToLower();
Un'altra opzione (che esaminerò tra un secondo) è quella di prendere l'attuale DateTimeFormatInfo, creare una copia e impostare i designatori am / pm sulla versione minuscola. Quindi utilizzare le informazioni sul formato per la normale formattazione. Dovresti memorizzare nella cache DateTimeFormatInfo, ovviamente ...
EDIT: nonostante il mio commento, ho comunque scritto la parte cache. Probabilmente non sarà più veloce del codice sopra (in quanto comporta un blocco e una ricerca nel dizionario) ma semplifica il codice chiamante:
string formatted = item.PostedOn.ToString("dddd, MMMM d, yyyy a\\t h:mmtt",
GetLowerCaseInfo());
Ecco un programma completo per dimostrare:
using System;
using System.Collections.Generic;
using System.Globalization;
public class Test
{
static void Main()
{
Console.WriteLine(DateTime.Now.ToString("dddd, MMMM d, yyyy a\\t h:mmtt",
GetLowerCaseInfo());
}
private static readonly Dictionary<DateTimeFormatInfo,DateTimeFormatInfo> cache =
new Dictionary<DateTimeFormatInfo,DateTimeFormatInfo>();
private static object cacheLock = new object();
public static DateTimeFormatInfo GetLowerCaseInfo()
{
DateTimeFormatInfo current = CultureInfo.CurrentCulture.DateTimeFormat;
lock (cacheLock)
{
DateTimeFormatInfo ret;
if (!cache.TryGetValue(current, out ret))
{
ret = (DateTimeFormatInfo) current.Clone();
ret.AMDesignator = ret.AMDesignator.ToLower();
ret.PMDesignator = ret.PMDesignator.ToLower();
cache[current] = ret;
}
return ret;
}
}
}
Altri suggerimenti
È possibile dividere la stringa di formato in due parti, quindi minuscola la parte AM / PM, in questo modo:
DateTime now = DateTime.Now;
string nowString = now.ToString("dddd, MMMM d, yyyy a\\t h:mm");
nowString = nowString + now.ToString("tt").ToLower();
Tuttavia, penso che la soluzione più elegante sia quella di utilizzare un DateTimeFormatInfo
istanza che costruisci e sostituisci AMDesignator
e PMDesignator
proprietà con " am " e " pm " rispettivamente:
DateTimeFormatInfo fi = new DateTimeFormatInfo();
fi.AMDesignator = "am";
fi.PMDesignator = "pm";
string nowString = now.ToString("dddd, MMMM d, yyyy a\\t h:mmtt", fi);
Puoi utilizzare l'istanza DateTime
per personalizzare molti altri aspetti della trasformazione di string
in <=>.
EDIT : l'esempio di Jon è molto migliore, anche se penso che il metodo di estensione sia ancora la strada da percorrere, quindi non è necessario ripetere il codice ovunque. Ho rimosso il primo esempio di Jon sostituito e sostituito sul metodo di estensione. Le mie app sono in genere app Intranet e non devo preoccuparmi delle culture non statunitensi.
Aggiungi un metodo di estensione per farlo per te.
public static class DateTimeExtensions
{
public static string MyDateFormat( this DateTime dateTime )
{
return dateTime.ToString("dddd, MMMM d, yyyy a\\t h:mm") +
dateTime.ToString("tt").ToLower();
}
}
...
item.PostedOn.MyDateFormat();
MODIFICA : altre idee su come farlo in Come formattare un DateTime come & Quot; Oct. 10, 2008 10:43 CST & Quot; in C # .
Il problema con gli approcci di cui sopra è che il motivo principale per cui si utilizza una stringa di formato è di abilitare la localizzazione e gli approcci forniti finora si spezzerebbero per qualsiasi paese o cultura che non desideri includere un am o pm finale. Quindi quello che ho fatto è stato scritto un metodo di estensione che comprende una sequenza di formato aggiuntiva 'TT' che indica una minuscola am / pm. Il codice seguente è sottoposto a debug per i miei casi, ma potrebbe non essere ancora perfetto:
/// <summary>
/// Converts the value of the current System.DateTime object to its equivalent string representation using the specified format. The format has extensions over C#s ordinary format string
/// </summary>
/// <param name="dt">this DateTime object</param>
/// <param name="formatex">A DateTime format string, with special new abilities, such as TT being a lowercase version of 'tt'</param>
/// <returns>A string representation of value of the current System.DateTime object as specified by format.</returns>
public static string ToStringEx(this DateTime dt, string formatex)
{
string ret;
if (!String.IsNullOrEmpty(formatex))
{
ret = "";
string[] formatParts = formatex.Split(new[] { "TT" }, StringSplitOptions.None);
for (int i = 0; i < formatParts.Length; i++)
{
if (i > 0)
{
//since 'TT' is being used as the seperator sequence, insert lowercase AM or PM as appropriate
ret += dt.ToString("tt").ToLower();
}
string formatPart = formatParts[i];
if (!String.IsNullOrEmpty(formatPart))
{
ret += dt.ToString(formatPart);
}
}
}
else
{
ret = dt.ToString(formatex);
}
return ret;
}
Questo dovrebbe essere il più performante di tutte queste opzioni. Ma peccato che non potessero funzionare in un'opzione minuscola nel formato DateTime (tt opposto a TT?).
public static string AmPm(this DateTime dt, bool lower = true)
{
return dt.Hour < 12
? (lower ? "am" : "AM")
: (lower ? "pm" : "PM");
}