y yo pensaba que convertir fechas y horas ya no sería más un calentamiento de cabeza

 

Pues eso… que sigue siendo… al menos si utilizas "tu formato preferido", aunque sea con otro "locale"… en fin… que no recuerdo yo desde cuando no tenía problemas para convertir una cadena con el formato de una fecha (supuestamente de forma correcta) a un objeto de tipo DateTime. A la memoria me vienen los tiempos del VB6 (o cualquier otro anterior a VB.NET) y sobre todo me acuerdo de cuando estaba escribiendo el código de mis foros con Visual Studio 2005 (ASP.NET 2.0).

Y hoy va y me da este regalito el Visual Studio 2012:

 

error al convertir fechas
Figura 1. Error al convertir 31/01/2013 20:40:00 a una fecha…

Así que… he tenido que optar por "salir del paso" convirtiendo "a mano" esas fechas erróneas y a usar el formato "yankee" para no tener problemas posteriores… espero que así sea…

 

Te explico que todo ese "follón" es porque quiero guardar el contenido de una clase definida por mí mismo en los "settings" de Windows 8, con idea de poder usarla la próxima vez que ejecute la aplicación.

En mi clase he sobrescrito el método ToString para que devuelva una cadena que posteriormente la pueda pasar desde lo que es, un tipo string, al tipo que he definido. Y ese ToString tiene el equivalente FromString para que devuelva un objeto usando el contenido de una cadena (con el formato que previamente he definido… o casi).

El "problema" era que yo dejaba que el propio .NET se encargara de convertir la fecha en cadena, es decir, no usaba ningún formato específico, por tanto el formato devuelto es: #d/M/yyyy h:m:sAM/PM# (o más o menos) y claro, la cadena usada era diferente… total un follón.

Así que… además de la comprobación manual, ahora lo que he hecho es que el método ToString devuelve la fecha con este formato: Fecha.ToString("#M/d/yyyy HH:mm:00#") y que salga el sol por Antequera

El "00" para los segundo es porque en este caso quiero que los segundos siempre sean 00, ya que es para una alarma en la que ese espacio de tiempo no se tiene en cuenta…

 

Te muestro parte del código que ahora estoy usando y lo que he tenido que hacer para salir del paso… (sabiendo que el error es porque el formato es dd/MM/yyyy HH:mm:ss, por eso no hay más comprobaciones en el caso de que falle la conversión del DateTime.TryParse.

 

Private Const elSeparador As String = ","

''' <summary>
''' Devuelve una cadena con los datos básicos:
''' Fecha y Mensaje.
''' Si se devuelven más datos, 
''' devolver el mensaje siempre al final.
''' </summary>
Public Overrides Function ToString() As String
    Return String.Format("{0}{2} {1}", Fecha.ToString("#M/d/yyyy HH:mm:00#"), Mensaje, elSeparador)
End Function

''' <summary>
''' Devuelve un objeto Alarma a partir del contenido
''' de una cadena, en el formato: "Fecha, Mensaje"
''' (el devuelto por <see cref="ToString"/>)
''' En lugar de la coma se usará el caracter indicado en <see cref="elSeparador"/>
''' </summary>
Public Shared Function FromString(s As String) As Alarma
    Dim it As New Alarma

    Dim i = s.IndexOf(elSeparador)
    If i = -1 Then
        Return Nothing
    End If

    If DateTime.TryParse(s.Substring(0, i), it.Fecha) = False Then
        Dim s1 = s.Substring(0, i)
        ' si da el error es porque está en formato dd/MM/yyyy HH:mm:ss
        Dim dia = CInt(s1.Substring(0, 2))
        Dim mes = CInt(s1.Substring(3, 2))
        Dim año = CInt(s1.Substring(6, 4))
        Dim hora = CInt(s1.Substring(11, 2))
        Dim minuto = CInt(s1.Substring(14, 2))
        it.Fecha = New DateTime(año, mes, dia, hora, minuto, 0)
    End If
    'it.Fecha = CDate(s.Substring(0, i))
    it.Mensaje = s.Substring(i + 1).TrimStart()

    Return it
End Function

 

Sólo lo muestro en VB porque en C# no lo estoy usando para este programa, pero como comprobarás no es un código demasiado complicado… creo… 😉

 

Pues ya está… ahí queda eso… para que no te confíes con las fechas desde cadena… 😉

 

Nos vemos.

Guillermo

10 comentarios en “y yo pensaba que convertir fechas y horas ya no sería más un calentamiento de cabeza

  1. kunecol

    ok, q bueno saberlo para futuros problemas de datetime, que tambien é tenido choques con los datos de fechas, y siempre me ayuda a solucionarlos son las entregas y foros del ¡¡¡ SEÑOR GUILLE !!! vos sos un maestro no es esta rama, claro un neto en programación le entrega a sus subditos las soluciones, tal como lo hace el Dios verdadero a sus fieles siervos, les da el conocimiento mediante su palabra…. gracias…

    Responder
  2. Mario

    Como bien dices en otros artículos: «hay muchas maneras de hacer lo mismo» (o algo así)…
    Yo adopté el ISO 8601 (yyyy-MM-ddThh:mm:ss) para guardar y recuperar cadenas que contienen fechas y nunca he tenido problemas.
    Saludos elGuille, aprendo mucho de tus posteos, pero también quería aportar algo.

    Responder
  3. GodShaka

    Vale pues, que abra que checar como pega con un simple date o time si referencio a SQL… solo por curiosidad… por que usar CDate en lugar de DateTime.Parse(«31/01/2012», CultureInfo.CreateSpecificCulture(«es-MX»))
    por ejemplo??

    Responder
  4. elGuille

    Lo del CDate es más por comodidad que por otra cosa, en realidad prefiero el TryParse, pero cuando haces las cosas «de rápido», pues… a lo más sencillo… 🙂

    Con el SQL y asignando los valores usando parámetros (@fecha, etc.) normalmente no he tenido problemas… y ahí es más importante no tener fallos, jeje

    Responder
  5. elGuille

    Gracias Rnz, y mi sitio (www.elguille.info) desde finales de 1996, lo que pasa que ahora casi todas las cosas nuevas las publico en el blog que es más cómodo 🙂

    Responder
  6. cesar

    buenos post Guille , yo le ando en .Net pero en el trabajo empece con VB6.0
    y valla que la gran amyoria de las veces las respuestas las en econtrado por aqui , mil gracias , Saludos desde Lima-Perú , un abrazo

    Responder

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *