2008-10-07 25 views
35

Conozco la clase System.TimeZone, así como los diversos usos del método DateTime.ToString(). Lo que no he podido encontrar es una forma de convertir un DateTime a una cadena que, además de la información de fecha y hora, contiene la abreviatura de tres letras de Time Zone (de hecho, de forma muy parecida a la información de herramientas de StackOverflow para la visualización del tiempo funciona).¿Cómo se muestra DateTime con una zona horaria abreviada?

Para hacer que un ejemplo sea fácil de seguir para todos, así como para consumir, continuemos con el ejemplo de StackOverflow. Si observa la información sobre herramientas que se muestra en tiempos relativos, se muestra con la fecha completa, el tiempo que incluye segundos en formato de doce horas, una designación AM/PM y luego la abreviatura de Zona horaria de tres letras (en su caso, Coordinado Tiempo Universal). Me doy cuenta de que podría obtener fácilmente GMT o UTC utilizando los métodos integrados, pero lo que realmente quiero es la hora, ya que es localmente — en este caso, en un servidor web.

Si nuestro servidor web ejecuta Windows Server 2k3 y tiene su zona horaria configurada en CST (o, hasta que daylight saving cambie, CDT ¿verdad?), Me gustaría que nuestra aplicación web ASP.NET muestre DateTimes relativa a esa zona horaria, así como el formato para mostrar un "CST" en el extremo. Me doy cuenta de que podría codificar fácilmente esto, pero en aras de la solidez, realmente preferiría una solución basada en el servidor que ejecuta la configuración del entorno del sistema operativo del código.

En este momento, tengo todo, pero la abreviatura de zona horaria usando el siguiente código:

myDateTime.ToString("MM/dd/yyyy hh:mm:ss tt") 

que muestra:

10/07/2008 03:40:31 PM

Todos Quiero (y que no es mucho, prometen!) es para que diga:

10/07/2008 03:40:31 PM CDT

Puedo usar System.TimeZone.CurrentTimeZone y usarlo para mostrar correctamente "Central Daylight Time" pero ... eso es demasiado largo por motivos de brevedad. ¿Estoy atascado escribiendo una rutina de manipulación de cadenas para quitar el espacio en blanco y las letras que no sean mayúsculas? Mientras que eso podría funcionar, eso parece increíblemente piratearme ...

Googling y mirando por aquí no produjo nada aplicable a mi pregunta específica.

Respuesta

1

Depende del nivel de robustez que necesite.

Probablemente necesites algún tipo de truco en ambos sentidos. Una manera fácil sería dividir la cadena por espacios y luego concatenar la primera letra de cada palabra. es decir,

string[] words = tzname.Split(" ".ToCharArray()); 
string tzabbr = ""; 
foreach (string word in words) 
    tzabbr += word[0]; 

Eso no funcionará para todas las zonas horarias en el planeta, pero funcionará para la mayoría de ellos. Si lo necesita más sólido, probablemente necesite crear un mapa que asigne nombres de zonas horarias a sus abreviaturas.

2

Crearía una tabla de búsqueda que convierta el nombre de la zona horaria a su abreviatura. Si no se encuentra la coincidencia, puede devolver el nombre completo de la zona.

Ver time zone abbreviations.

6

Hay una biblioteca disponible gratuitamente, TZ4NET, que tiene estas abreviaturas disponibles. Antes de .NET 3.5, esta era una de las únicas alternativas para convertir entre zonas horarias también.

Si no desea una biblioteca separada, puede generar un mapa de abreviaturas razonables utilizando las clases TimeZoneInfo y luego solo suminístrelas a su usuario.

19

Aquí está mi método de hack rápido que acabo de hacer para solucionar este problema.

public static String TimeZoneName(DateTime dt) 
{ 
    String sName = TimeZone.CurrentTimeZone.IsDaylightSavingTime(dt) 
     ? TimeZone.CurrentTimeZone.DaylightName 
     : TimeZone.CurrentTimeZone.StandardName; 

    String sNewName = ""; 
    String[] sSplit = sName.Split(new char[]{' '}); 
    foreach (String s in sSplit) 
     if (s.Length >= 1) 
      sNewName += s.Substring(0, 1); 

    return sNewName; 
} 
+5

Este enfoque tiene algunos defectos. Por ejemplo, en Arizona, donde usan Mountain Standard Time y no observan el horario de verano, .NET tiene un DaylightName y un StandardName de "US Mountain Standard Time" que mostrará "UMST" con su método. Esperaría ver "MST" en su lugar (tanto durante el verano como en invierno). Lamentablemente, el .NET Framework parece quedarse corto aquí, así que he recurrido a una tabla de búsqueda estática. – codemonkey

+0

Esto no funcionará para tantas zonas horarias, p. ** ACT ** _Acre Time_ (UTC -5) – Tanmay

2

Si tirando de la abreviatura de la DaylightName/StandardName, vas a ser mejor de la construcción de la cadena mediante un StringBuilder, para las cadenas son inmutables.

public static string ToCurrentTimeZoneString(this DateTime date) 
    { 
     string name = TimeZone.CurrentTimeZone.IsDaylightSavingTime(date) ? 
      TimeZone.CurrentTimeZone.DaylightName : 
      TimeZone.CurrentTimeZone.StandardName; 
     return name; 
    } 

    public static string ToCurrentTimeZoneShortString(this DateTime date) 
    { 
     StringBuilder result = new StringBuilder(); 

     foreach (string value in date.ToCurrentTimeZoneString().Split(' ')) 
     { 
      if (value.IsNotNullOrEmptyWithTrim()) 
      { 
       result.Append(char.ToUpper(value[0])); 
      } 
     } 

     return result.ToString(); 
    } 

Por supuesto, una matriz que contiene KeyValuePair es probablemente la mejor para una empresa multinacional. Si quiere afeitarse unos minutos después de una fecha límite apretada, y está en una empresa de EE. UU., Esto funciona.

+1

Creo que la concatenación de cadenas de tres caracteres no es del todo mala y no justifica el uso de un StringBuilder aquí, especialmente porque de todos modos estás caminando de izquierda a derecha. – Martijn

0

Ok, Ya han pasado 4 años (y casi una semana), es el momento hemos traído LINQ en la discusión ...

Juntar Criag de e ideas de Bob ...

public static String TimeZoneName2(DateTime dt) 
{ 
    var return ToCurrentTimeZoneShortString(dt) 
       .Split(new char[]{' '}, StringSplitOptions.RemoveEmptyEntries); 
    return sSplit.Aggregate("", (st,w)=> st +=w[0]); 
} 

A menos que usted puede confiar zona horaria a no devolver una cadena con dos espacios consecutivos:

public static String TimeZoneName3(DateTime dt) 
{ 
    return ToCurrentTimeZoneShortString(dt).Split(' ') 
       .Aggregate("", (st,w)=> st +=w[0]); 
} 
0

Si está utilizando < = .Net 3.0 a continuación, descargar y utilizar TZ4Net OlsonTimeZone.CurrentTimeZone .Abreviatura estándar para> .Net 3.0 usa NodaTime u otro. Los nombres de las zonas horarias no se ajustan a ninguna convención en la que pueda confiar en la manipulación simple de cadenas para construir la abreviatura de un acrónimo. Incorrecto el 5% de las veces sigue siendo incorrecto.

+0

¿Va a dejar de obtener ganancias el 95% del tiempo? – micahhoover

2

Utilice nodatime.

La siguiente función toma DateTime en hora UTC y la formatea con zona horaria abreviada del sistema local. Use x en la cadena de formato para la zona horaria abreviada. Busque el formato personalizado here.

public static string ConvertToFormattedLocalTimeWithTimezone(DateTime dateTimeUtc) 
    { 
     var tz = DateTimeZoneProviders.Tzdb.GetSystemDefault(); // Get the system's time zone 
     var zdt = new ZonedDateTime(Instant.FromDateTimeUtc(dateTimeUtc), tz); 
     return zdt.ToString("MM'/'dd'/'yyyy' 'hh':'mm':'ss' 'tt' 'x", CultureInfo.InvariantCulture); 
    } 
Cuestiones relacionadas