2009-08-18 28 views
10

Me he encontrado con un problema que probablemente se deba a mi error de comprensión sobre cómo funciona el método DateTime.ToShortTimeString(). Cuando el formato de cadenas de tiempo con esta función, estaba asumiendo que respetaría el "tiempo corto" puesta en Opciones de formato de Windows 7.¿Por qué DateTime.ToShortTimeString() no respeta el formato de tiempo corto en "Configuración regional y de idioma"?

Control Panel -> Clock, Language and Region -> Region and Language -> Formats Tab.

Sin embargo .NET parece para seleccionar un formato de corta duración no se basa en esta configuración, pero basada en la cultura actual:

Region and Language -> Location -> Current Location

hice algunas pruebas en Windows 7 RC:

 
Culture: en-GB, 6AM: 06:00, 6PM: 18:00 // HH:mm (United Kingdom) 
Culture: en-GB, 6AM: 06:00, 6PM: 18:00 // hh:mm (United Kingdom) 
Culture: en-US, 6AM: 6:00 AM, 6PM: 6:00 PM // HH:mm (United States) 
Culture: en-US, 6AM: 6:00 AM, 6PM: 6:00 PM // hh:mm (United States) 
Culture: el-GR, 6AM: 6:00 πμ, 6PM: 6:00 μμ // HH:mm (Greece) 
Culture: el-GR, 6AM: 6:00 πμ, 6PM: 6:00 μμ // hh:mm (Greece) 

utilicé el-GR ya que era la cultura que el usuario que repor con el problema, también probó esto en Vista SP2 y Win 7 RC con el mismo resultado.

La pregunta es en realidad doble: 1) ¿Cuál es mi incomprensión de los formatos .NET y Windows? 2) ¿Cuál es la mejor solución para crear una cadena de tiempo de formato corto (HH: mm o hh: mm tt) basada en el sistema operativo, idealmente debería funcionar en Mono así que preferiría evitar leer desde el registro o P/Invocar.

Método utilizado para generar lo anterior, para futuras referencias y pruebas.

[STAThread] 
static void Main(string[] args) 
{ 
    CultureInfo culture = CultureInfo.CurrentCulture; 

    DateTime sixAm = new DateTime(2009, 07, 05, 6, 0, 0); // 6AM 
    DateTime sixPm = new DateTime(2009, 07, 05, 18, 0, 0); // 6PM 

    string sixAmString = sixAm.ToShortTimeString(); 
    string sixPmString = sixPm.ToShortTimeString(); 

    string format = "Culture: {0}, 6AM: {1}, 6PM: {2}"; 

    string output = String.Format(format, culture, sixAmString, sixPmString); 
    Console.WriteLine(output); 
    Clipboard.Clear(); 
    Clipboard.SetText(output); 

    Console.ReadKey(); 
} 

Actualización: Basándose en los comentarios de Mike a continuación Adapté el método anterior con los siguientes cambios:

Los siguientes dos líneas

string sixAmString = sixAm.ToShortTimeString(); 
string sixPmString = sixPm.ToShortTimeString(); 

cambiado a

string sixAmString = sixAm.ToString("t", culture); 
string sixPmString = sixPm.ToString("t", culture); 

I als o Cambió la variable de cultivo para usar CultureInfo.CurrentUICulture.

Esto desafortunadamente no funciona tan bien como esperaba, la salida independientemente de la configuración de tiempo corto en la pestaña Formatos de Windows 7 fue:

 
Culture: en-US, 6AM: 6:00 AM, 6PM: 6:00 PM 

parece que el CultureInfo.CurrentUICulture es siempre en- NOS.

Respuesta

1

En respuesta a cada una de mis preguntas:

1) ¿Cuál es mi falta de comprensión de formatos .NET y Windows?

La respuesta corta es que no hay ningún vínculo entre la configuración de "Tiempo corto" en "Configuración regional y de idioma" y la propiedad ShortTimePattern de .NET. Sin embargo, la propiedad LongTimePattern viene dictada por la configuración "Long Time".

I adaptado el método anterior sustitución de las dos líneas de formato a:

string sixAmString = sixAm.ToString("T", culture.DateTimeFormat); 
string sixPmString = sixPm.ToString("T", culture.DateTimeFormat); 

Aquí está la salida:

 
Culture: en-GB, 6AM: 06:00:00, 6PM: 18:00:00 // HH:mm:ss 
Culture: en-GB, 6AM: 06:00:00 AM, 6PM: 06:00:00 PM //hh:mm:ss tt 

La parte inferior de this article explicó el problema para mí.

2) ¿Cuál es la mejor solución para crear una cadena de tiempo de formato corto (HH: mm o hh: mm tt) según la configuración del sistema operativo?

No conozco la mejor solución, pero creé la siguiente función que convierte el LongTimeFormat en un ShortTimeFormat permitiendo así que una aplicación siga la opción de los usuarios si cambian el "Long Time" (aunque no lo ganó) t seguir el ajuste de "Tiempo corto").

static string GetShortTimeString(DateTime ShortTimeString) 
{ 
    DateTimeFormatInfo dateTimeFormat = CultureInfo.CurrentCulture.DateTimeFormat; 
    string ShortTimePattern = dateTimeFormat.LongTimePattern.Replace(":ss", String.Empty); 
    ShortTimePattern = ShortTimePattern.Replace(":s", String.Empty); 

    return ShortTimeString.ToString(ShortTimePattern); 
} 

La salida después de hacer los cambios anteriores:

 
Culture: en-GB, 6AM: 06:00, 6PM: 18:00 
Culture: en-GB, 6AM: 06:00 AM, 6PM: 06:00 PM 

El P/opción Invoke es utilizar GetTimeFormat pasar los TIME_NOSECONDS utilizando DateTime.ToString (Formato) como anteriormente. No he probado esto, ya que preferiría evitar el uso de P/Invoke.

5

respuesta a la segunda pregunta es

DateTimeFormat.Format(DateTime.Now, "t", CultureInfo.CurrentUICulture); 

o

DateTime.Now.ToString("t", CultureInfo.CurrentUICulture); 

En realidad es siempre mejor utilizar métodos explícitos que aceptan CultureInfo. No hay consistencia en cómo .Net elige qué usar de forma predeterminada, ya sea CurrentCulture o CurrentUICulture o InvarinatCulture.

Para completar la respuesta. También describiré las diferencias entre culturas.

Así que CurrentCulture es "Panel de control -> Reloj, idioma y región -> Región e idioma -> ficha Formatos". Esta es la cultura que espera que sean sus cálculos.Por ejemplo, puede realizar su contabilidad en EE. UU., Por lo que debe configurar esto en los EE. UU.

CurrentUICulture es "Región e idioma -> Idioma de visualización", significa que cuando es un emigrante de Ucrania, desea que su aplicación se ubique en UA (pero todos los cálculos siguen en EE. UU.).

Y a InvariantCulture se lo conoce como culture agnostic locale. Debe usar esto para almacenar información, etc. Efectivamente es En-US.

Nota: podría estar equivocado en cada ubicación ubicada en Windows. Pero probablemente tengas una idea.

+0

Gracias, haré algunas pruebas con eso y me pondré en práctica. ¿Qué otra cosa se ve afectada por el cultivo que no sean separadores de fecha, hora, moneda, decimal y mil? –

+1

Mes, nombres de días laborables. Direcciones LTR/RTL. Clasificación de cadenas. Operaciones de mayúsculas/minúsculas con cadenas. Publicación por entregas. –

+0

CultureInfo.CurrentUICulture parece ser en EE. UU., ¿En qué otro lugar podría configurarse? Intenté volver a enviar el cheque después de comprobar que todo estaba configurado en el Reino Unido. También noté que, a veces, después de ejecutar el programa, no recogen el cambio de cultura inmediatamente. Sin embargo, ejecutarlo por segunda vez siempre lo recoge. –

2

Estoy bastante seguro de que el string de formato de tiempo corto no se usa en DateTime.ToShortTimeString() o DateTime.ToString ("t") es un error, porque fue corregido en .NET framework 4.0.

+0

esta debería ser la respuesta aceptada ya que esto explica por qué el ShortTimePattern no usa la configuración de región actual. Rápido de verificar con una prueba unitaria en un proyecto 3.5 y uno en un proyecto 4.0 y verá que el 3.5 ignora lo que esté configurado en el diálogo de región e idioma – nrjohnstone

Cuestiones relacionadas