2009-01-31 27 views
43

Voy a obtener un formato personalizado de fecha y hora que incluya el designador AM/PM, pero quiero que el "AM" o "PM" sean minúsculas sin haciendo que el resto de los caracteres en minúsculas.Obtenga AM/PM para una fecha y hora en minúsculas usando solo un formato de fecha y hora

Es esto posible utilizando un formato único y sin utilizar una expresión regular?

Esto es lo que tengo en este momento:

item.PostedOn.ToString("dddd, MMMM d, yyyy a\\t h:mmtt") 

Un ejemplo de la salida en este momento sería sábado por la, 31 de enero de 2009 a 13:34

+0

Más información en http://stackoverflow.com/questions/448634/how-to-format-a-datetime-like-oct-10-2008-1043am-cst-in-c – tvanfosson

Respuesta

57

yo personalmente formatearlo en dos partes: la parte no-am/pm, y la parte de am/pm con ToLower:

string formatted = item.PostedOn.ToString("dddd, MMMM d, yyyy a\\t h:mm") + 
        item.PostedOn.ToString("tt").ToLower(); 

Otra opción (que voy a investigar en un segundo) es para agarrar la corriente DateTimeFormatInfo, crear una copia, y establecer las am/pm designadores a la versión en minúsculas. Luego use esa información de formato para el formato normal. Lo que quiere almacenar en caché el DateTimeFormatInfo, obviamente ...

EDIT: A pesar de mi comentario, he escrito el bit de almacenamiento en caché de todos modos. Probablemente no será más rápido que el código anterior (ya que implica una cerradura y una búsqueda de diccionario) pero sí lo hace el código de llamada simple:

string formatted = item.PostedOn.ToString("dddd, MMMM d, yyyy a\\t h:mmtt", 
              GetLowerCaseInfo()); 

Aquí es un programa completo para demostrar:

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; 
     } 
    } 
} 
+0

Me gusta este mejor que cualquier cosa publicada en esa otra pregunta ... ¡gracias! –

+0

¿El código publicado o la idea de un nuevo DateTimeFormatInfo? Si es el último, te daré un código para ti. Si es el primero, no molestaré :) DateTimeFormatInfo.Clone() es probablemente el camino a seguir. –

+0

La primera - la última, aunque sumamente asombrosa, es demasiado excesiva en este caso. –

1

EDITAR: Jon el ejemplo es mucho mejor, aunque creo que el método de extensión sigue siendo el camino a seguir, por lo que no tiene que repetir el código en todas partes. Quité el reemplazo y sustituí el primer ejemplo de Jon en su lugar en el método de extensión. Mis aplicaciones suelen ser aplicaciones de intranet y no tengo que preocuparme por las culturas que no pertenecen a los EE. UU.

Añadir un método de extensión para hacer esto para usted.

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(); 

EDITAR: Otras ideas sobre cómo hacer esto en How to format a DateTime like "Oct. 10, 2008 10:43am CST" in C#.

+0

maaaan eso es exactamente lo que esperaba evitar :( –

+0

Tampoco funciona para cultivos con designadores AM/PM distintos a AM/PM. –

+0

Lo que Jon dijo. Y tiene el potencial de funcionar como un bork en un lugar donde AM se considera parte del nombre del día (improbable, pero aún está en mal estado a partir de un POV correcto). Es mejor utilizar un formato separado para la parte am/pm, ToLower(), y añádalo. – Mark

18

Se podría dividir la cadena de formato en dos partes, y luego en minúsculas la parte PM/AM, así:

DateTime now = DateTime.Now; 
string nowString = now.ToString("dddd, MMMM d, yyyy a\\t h:mm"); 
nowString = nowString + now.ToString("tt").ToLower(); 

Sin embargo, creo que el más el solución egant es utilizar un DateTimeFormatInfo instance que se construye y reemplazar los AMDesignator y PMDesignator propiedades con "am" y "pm", respectivamente:

DateTimeFormatInfo fi = new DateTimeFormatInfo(); 

fi.AMDesignator = "am"; 
fi.PMDesignator = "pm"; 

string nowString = now.ToString("dddd, MMMM d, yyyy a\\t h:mmtt", fi); 

Usted puede utilizar la instancia DateTimeFormatInfo de personalizar muchos otros aspectos de la transformación de una DateTime a a string.

+0

Prefiero este enfoque porque la variable "ahora" no está tan disponible para mí: tengo una expresión de DataBind complicada que se vería fea y esto lo maneja todo en una llamada a función. – umbyersw

+1

Me gusta el enfoque DateTimeFormatInfo, especialmente porque tenemos algunos casos en los que nos gustaría mostrar "a.m." y "p.m." (incluidos los períodos), lo que hace que la solución ToLower() sea mucho más complicada. – JackAce

+0

O simplemente 'now.ToString (" dddd, MMMM d, aaaa a \\ t h: mmtt ", new DateTimeFormatInfo {AMDesignator =" am ", PMDesignator =" pm "});' –

1

El problema con los enfoques anteriores es que la razón principal por la que utiliza una cadena de formato es habilitar la localización, y los enfoques dados hasta ahora se romperían para cualquier país o cultura que no desee incluir una am o pm final.Entonces, lo que hice fue escrito un método de extensión que comprende una secuencia de formato adicional 'TT' que significa una letra min/pm en minúscula. El código siguiente se depura para mis casos, pero puede no ser perfecto:

/// <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; 
    } 
0

Este debería ser el mas potente de todas estas opciones. Pero es una lástima que no puedan funcionar en una opción en minúsculas en el formato DateTime (¿tt frente a TT?).

public static string AmPm(this DateTime dt, bool lower = true) 
    { 
     return dt.Hour < 12 
      ? (lower ? "am" : "AM") 
      : (lower ? "pm" : "PM"); 
    }