DateTime.ToString ("MM / dd / aaaa HH: mm: ss.fff") resultó en algo así como "14/09/2013 07.20.31.371"

131

Tengo una aplicación WP8, que enviará la hora actual a un servicio web.

Obtengo la cadena de fecha y hora llamando

DateTime.ToString("MM/dd/yyyy HH:mm:ss.fff")

Para la mayoría de los usuarios funciona muy bien y me da la cadena correcta como "09/10/2013 04:04:31.415". Pero para algunos usuarios, la cadena resultante es algo así "09/14/2013 07.20.31.371", lo que causa problemas en mi servicio web.

¿Es por algún problema de formato cultural? ¿Cómo puedo asegurarme de que la cadena de resultados esté delimitada por dos puntos en lugar de punto?

Eldorado
fuente
2
la única diferencia es colon vs punto.
Eldorado
Consulte .Net Standard 2 samples
Sina Lotfi

Respuestas:

244

¿Es por algún problema de formato cultural?

Si. Su usuario debe estar en una cultura donde el separador de tiempo es un punto. Tanto ":" como "/" se interpretan de manera sensible a la cultura en formatos de fecha y hora personalizados .

¿Cómo puedo asegurarme de que la cadena de resultados está delimitada por dos puntos en lugar de punto?

Sugeriría especificar CultureInfo.InvariantCulture:

string text = dateTime.ToString("MM/dd/yyyy HH:mm:ss.fff",
                                CultureInfo.InvariantCulture);

Alternativamente, puede citar los separadores de hora y fecha:

string text = dateTime.ToString("MM'/'dd'/'yyyy HH':'mm':'ss.fff");

... pero eso le dará resultados "interesantes" que probablemente no espere si consigue que los usuarios se ejecuten en una cultura donde el sistema de calendario predeterminado no es el calendario gregoriano. Por ejemplo, tome el siguiente código:

using System;
using System.Globalization;
using System.Threading;

class Test
{
    static void Main()        
    {
        DateTime now = DateTime.Now;
        CultureInfo culture = new CultureInfo("ar-SA"); // Saudi Arabia
        Thread.CurrentThread.CurrentCulture = culture;
        Console.WriteLine(now.ToString("yyyy-MM-ddTHH:mm:ss.fff"));
    }
} 

Eso produce una producción (el 18 de septiembre de 2013) de:

11/12/1434 15:04:31.750

¡Supongo que su servicio web se sorprendería de eso!

De hecho, sugeriría no solo usar la cultura invariante, sino también cambiar a un formato de fecha ISO-8601:

string text = dateTime.ToString("yyyy-MM-ddTHH:mm:ss.fff");

Este es un formato más aceptado a nivel mundial: también se puede ordenar y hace que el orden de mes y día sea obvio. (Mientras que el 07/06/2013 podría interpretarse como el 7 de junio o el 6 de julio, dependiendo de la cultura del lector).

Jon Skeet
fuente
gracias Jon Pensé que la cadena de resultado sería exactamente como la cadena de formato. Intentaré tu sugerencia.
Eldorado
3
Solo una pequeña consideración. Al cargar un objeto CultureInfo desde un código específico, siempre sugiero establecer el useUserOverrideparámetro en falso, de lo contrario, algunas configuraciones de usuario pueden anular las configuraciones culturales. Por ejemplo, en su caso, sugiero usar new CultureInfo("ar-SA", false).
Davide Icardi
@DavideIcardi: Interesante, gracias, aunque en este caso el propósito de usar Arabia Saudita fue específicamente decir por qué usar la cultura invariante probablemente sea correcto. Sin embargo, lo tendré en cuenta para futuras publicaciones.
Jon Skeet
77
A mitad de esta extensa respuesta, comencé a preguntarme: ¿sería Jon nuevamente? Sí.
Mueca de desesperación
¿Cómo gestionar lo mismo con Html.TextBoxFor (x => x.Date, "{0: MM / dd / aaaa}")?
VISHMAY
9

:tiene un significado especial: es el separador de tiempo. ( Cadenas de formato de fecha y hora personalizadas ).

Use \para escapar de ella:

DateTime.ToString(@"MM/dd/yyyy HH\:mm\:ss.fff")

O use CultureInfo.InvariantCulture:

DateTime.ToString("MM/dd/yyyy HH:mm:ss.fff", CultureInfo.InvariantCulture)

Sugeriría ir con el segundo, porque también /tiene un significado especial (es El separador de fecha ), por lo que también puede tener problemas con eso.

MarcinJuraszek
fuente
2
No es solo que el separador de fechas sea un problema: vea mi respuesta para ver un ejemplo de la cultura que también afecta los números reales ...
Jon Skeet
1
¡No se le escapa!
Shereef Marzouk
8

Puede usar InvariantCulture porque su usuario debe estar en una cultura que use un punto en lugar de dos puntos:

DateTime.ToString("MM/dd/yyyy HH:mm:ss.fff", CultureInfo.InvariantCulture);
Jon La Marr
fuente
7

Me encontré con este problema últimamente con Windows 10 desde otra dirección, y encontré la respuesta de @JonSkeet muy útil para resolver mi problema.

También investigué un poco más con un formulario de prueba y descubrí que cuando la cultura actual se estableció en "no"o "nb-NO"en tiempo de ejecución ( Thread.CurrentThread.CurrentCulture = new CultureInfo("no");), la llamada ToString ("aaaa-MM-dd HH: mm: ss") respondió de manera diferente en Windows 7 y Windows 10. ¡Devolvió lo que esperaba en Windows 7 y HH.mm.ss en Windows 10!

¡Creo que esto da un poco de miedo! Como creía que una cultura era una cultura en cualquier versión de Windows al menos.

Håkon Seljåsen
fuente
Sería bastante curioso descubrir qué causa realmente esto.
Lauri Peltonen
2
Se ha reconocido y corregido como un error de localización de Windows 10. Por lo tanto, una actualización de Windows en la máquina cliente solucionará el problema. Más detalles están disponibles en esta publicación de blog: heikniemi.net/hardcoded/2015/08/…
Håkon Seljåsen
El blog de Jouni Heikniemi, que he vinculado anteriormente, parece estar roto. Las actualizaciones de Windows relevantes donde se han solucionado los problemas se enumeraron allí: 2015-10-09: KB3093266 - Windows 10 KB3088956 - Windows Server 2012 R2 y Windows 8.1 KB3088955 - Windows Server 2012 y Windows 8 KB3088957 - Windows 7 SP1, Windows Server 2008 SP2 , Windows Server 2008 R2 SP1 y Windows Vista SP2 Intentando vincular nuevamente al blog, esta vez a través de archive.org: web.archive.org/web/20161030193739/http://www.heikniemi.net/…
Håkon Seljåsen
4

Puedes usar String.Format:

DateTime d = DateTime.Now;
string str = String.Format("{0:00}/{1:00}/{2:0000} {3:00}:{4:00}:{5:00}.{6:000}", d.Month, d.Day, d.Year, d.Hour, d.Minute, d.Second, d.Millisecond);
// I got this result: "02/23/2015 16:42:38.234"
Cosmin
fuente
0

Convertir fecha en cadena

Utilice el nombre de espacio

using System.Globalization;

Código

string date = DateTime.ParseExact(datetext.Text, "dd-MM-yyyy", CultureInfo.InstalledUICulture).ToString("yyyy-MM-dd");
Hafsal
fuente
Esta no es la forma de convertir una fecha en una cadena. ¡Analizar es lo contrario!
Vincent Vancalbergh