lunes, 14 de enero de 2013

DateTime.Parse & Marzo

Hoy hemos visto un error super curioso, leemos un fichero plano donde las fechas llegan con el formato dd-MMM-yy ( el formato no está decidió por nosotros)

Resulta que en una aplicación

fecha = DateTime.Parse("20-JAN-09") funciona
fecha = DateTime.Parse("20-MAR-09") falla No se puede reconocer la cadena como valor DateTime válido.

El problema parece ser en que no sabe si “MAR” es Marzo o Martes y da un error que no puede convertir la fecha, puesto que nuestro sistema operativo está en español la referencia cultural que está usando es “es”

Solución , usar DateTime.Parse con referencia cultural o DateTime.ParseExact (incluye el formato)

https://connect.microsoft.com/VisualStudio/feedback/details/729674/datetime-parse-fails-to-parse-correct-dates-or-accepts-incorrect-dates


Por si aun tienes curiosidad

Try
Dim fecha As DateTime
fecha = DateTime.Parse("20-JAN-09")
' falla ---> fecha = DateTime.Parse("20-MAR-09")
fecha = DateTime.ParseExact("20-MAR-09", "dd-MMM-yy", System.Globalization.CultureInfo.GetCultureInfo("en-US"), System.Globalization.DateTimeStyles.None)
fecha = DateTime.Parse("20-MAR-09", System.Globalization.CultureInfo.GetCultureInfo("en"), System.Globalization.DateTimeStyles.None)
fecha = DateTime.Parse("20-MAR-09", System.Globalization.CultureInfo.GetCultureInfo("en"))
fecha = DateTime.Parse("20-JAN-09", System.Globalization.CultureInfo.GetCultureInfo("es"))
' falla fecha = DateTime.Parse("20-MAR-09", System.Globalization.CultureInfo.GetCultureInfo("es"))
fecha = DateTime.ParseExact("20-MAR-09", "dd-MMM-yy", System.Globalization.CultureInfo.GetCultureInfo("es"), System.Globalization.DateTimeStyles.None)
fecha = DateTime.Parse("20-APR-09", System.Globalization.CultureInfo.GetCultureInfo("es"))
'falla --> fecha = DateTime.Parse("20-AVR.-09", System.Globalization.CultureInfo.GetCultureInfo("es"))
fecha = DateTime.Parse("20-APR-09", System.Globalization.CultureInfo.GetCultureInfo("fr"))
Catch ex As Exception

End Try

Me sorprendió que
fecha = DateTime.Parse("20-APR-09", System.Globalization.CultureInfo.GetCultureInfo("es"))

Funciona!!!!   El formato no es español, pero según la documentación

Este método intenta analizar s completamente para evitar que se produzca FormatException. Si es posible, omite los datos no reconocidos y rellena la información que falta acerca de mes, día y año con la hora actual. Si s contiene sólo una fecha y ninguna hora, este método supone que es medianoche (00:00). Se omiten los caracteres de espacio en blanco iniciales, centrales o finales que pueda haber en s. La fecha y la hora pueden ir entre corchetes con un par de caracteres NUMBER SIGN iniciales y finales ('#', U+0023) y pueden terminar con uno o más caracteres NULL (U+0000).”


Para evitar el FormatException, termina usando la InvariantCulture (que está en inglés) y por eso funciona

6 comentarios:

  1. Gracias! bastante rebuscada esta falla! no le llego si no es por este foro ;)

    ResponderEliminar
  2. excelente muchas gracias. pero tengo 2000 o mas DateTime.Parse, como podria generalizar la referencia cultural

    ResponderEliminar
    Respuestas
    1. se soluciono globalizando en el global.asax ya que mi web.config trabaja con es-Mx, dejo la solución en el siguiente comentario

      Eliminar
    2. using System.Globalization;
      protected void Application_PreRequestHandlerExecute(object sender, EventArgs e)
      {
      CultureInfo ci = CultureInfo.CreateSpecificCulture("es-MX");
      DateTimeFormatInfo dtfi = ci.DateTimeFormat;
      dtfi.AbbreviatedDayNames = new string [] { "Do", "Lu", "Ma", "Mi", "Ju", "Vi", "Sa"};

      dtfi.AbbreviatedMonthNames = new string[] { "ene", "feb", "mar", "abr", "may", "jun", "jul", "ago", "sep", "oct", "nov", "dic", "" };

      CultureInfo.DefaultThreadCurrentCulture = ci;
      Thread.CurrentThread.CurrentUICulture = ci;
      Thread.CurrentThread.CurrentCulture = ci;
      }

      Eliminar