2011-02-09 24 views
7

si consigo una cadena desde la línea de comandos y se ve así:cadena convertido al System.DateTime en Fa #

'1-1-2011' 

¿Cómo puedo convertir esa cadena a un objeto DateTime en C#?

+2

posible duplicado de [F # - Analiza fechas] (http: // stackoverflow.com/questions/4158077/f-parse-dates) –

+0

@Sebastian P - similar, pero no creo que sea un duplicado exacto, las dos preguntas preguntan cómo analizar diferentes formatos de fecha, lo que en realidad lleva a respuestas diferentes. –

Respuesta

8

Usted puede hacerlo tan simple como esto:

let dateTime = System.DateTime.Parse "1-1-2011" 
8

Para añadir una cosa agradable a lo 7sharp9 escribió, si también quiere controlar los errores, se puede escribir:

match System.DateTime.TryParse "1-1-2011" with 
| true, date -> printfn "Success: %A" date 
| false, _ -> printfn "Failed!" 

Este no es obvio, porque el método TryParse tiene un byref<DateTime> como último argumento (y se usa usando out en C#), pero F # le permite llamar al método de esta manera.

19

En función de sus necesidades específicas, la clase de .NET DateTime tiene varios métodos estáticos para convertir cadenas a DateTime casos, estos son DateTime.Parse, DateTime.ParseExact, y DateTime.TryParse y sus varias sobrecargas.

@ 7sharp9 demostró la forma más básica de realizar el análisis de fecha, con una llamada directa al método DateTime.Parse. Pero donde las cosas se ponen interesantes en F # es con DateTime.TryParse. Mientras que DateTime.Parse lanzará una excepción si el análisis falla, la sobrecarga más simple de DateTime.TryParse tiene la firma string * byref<DateTime> -> bool que devolverá si el análisis tiene éxito al establecer el argumento byref en la fecha analizada si es verdadero, o en su valor predeterminado (null en este caso) . Sin embargo, la sintaxis para usar esto en F # es engorrosa (y de hecho no es agradable de ningún lenguaje .NET), por lo que el lenguaje F # se diseñó con una función especial que permite una convención de llamadas mucho más agradable para métodos como @Thomas Petricek fuera.

Pero incluso el patrón del tipo de retorno F # 's (bool, resultado) aquí no es ideal. La mayoría de las veces no necesita el valor predeterminado si falla un análisis. Una firma más bonita para DateTime.TryParse sería string -> option<DateTime>. Por suerte, podemos ampliar fácilmente DateTime como nos gusta:

type System.DateTime with 
    static member TryParseOption str = 
     match DateTime.TryParse str with 
     | true, r -> Some(r) 
     | _ -> None 

Utilizamos la extensión por encima de este modo:

match System.DateTime.TryParseOption "11/11/11" with 
| Some r -> stdout.WriteLine r 
| None -> stdout.WriteLine "none" 

¿Qué es más consistente con F # convenciones (como List.tryFind, por ejemplo). Pero incluso esto puede ser "mejor". Observe cómo nos estamos emparejando en el resultado del análisis de prueba. Usando Patrones Activos Parciales (¡por supuesto!), Podemos envolver toda una clase de análisis y mover la coincidencia a la caja de fósforos para una mayor flexibilidad. Tomemos el siguiente

open System 
let (|DateTime|_|) str = 
    match DateTime.TryParse str with 
    | true, dt -> Some(dt) 
    | _ -> None 

let (|Int|_|) str = 
    match Int32.TryParse str with 
    | true, num -> Some(num) 
    | _ -> None 

let (|Float|_|) str = 
    match Double.TryParse str with 
    | true, num -> Some(num) 
    | _ -> None 

uso de estos, podemos escribir una pequeña aplicación de consola ordenada:

let rec loop() = 
    stdout.WriteLine " 
Please select an option: 
    1) Parse something 
    2) Exit 
" 
    match stdin.ReadLine() with 
    | Int 1 -> 
     stdout.WriteLine "Enter something to parse: " 
     match stdin.ReadLine() with 
     | Int num -> stdout.WriteLine("Successfully parsed int: {0}", num) 
     | Float num -> stdout.WriteLine("Successfully parsed float: {0}", num) 
     | DateTime dt -> stdout.WriteLine("Successfully parsed DateTime: {0}", dt) 
     | _ -> stdout.WriteLine "Parse Failed!" 
     loop() 
    | Int 2 -> 
     stdout.WriteLine "Now exiting" 
    | _ -> 
     stdout.WriteLine "Invalid option, please try again" 
     loop() 

La clave a notar es el partido anidada, donde Int, Float, DateTime realizar su intento análisis sintáctico dentro la misma expresión del partido

Hay otras aplicaciones ordenadas de estos patrones activos también, por ejemplo, podemos filtrar y asignar una lista de cadenas de fecha sucinta simultáneamente

> ["11/23/2003"; "not a date"; "1/1/23 23:23pm"] |> Seq.choose(|DateTime|_|);; 
val it : seq<DateTime> = 
    seq 
    [11/23/2003 12:00:00 AM {Date = 11/23/2003 12:00:00 AM; 
          Day = 23; 
          DayOfWeek = Sunday; 
          DayOfYear = 327; 
          Hour = 0; 
          Kind = Unspecified; 
          Millisecond = 0; 
          Minute = 0; 
          Month = 11; 
          Second = 0; 
          Ticks = 632051424000000000L; 
          TimeOfDay = 00:00:00; 
          Year = 2003;}; 
    1/1/2023 11:23:00 PM {Date = 1/1/2023 12:00:00 AM; 
          Day = 1; 
          DayOfWeek = Sunday; 
          DayOfYear = 1; 
          Hour = 23; 
          Kind = Unspecified; 
          Millisecond = 0; 
          Minute = 23; 
          Month = 1; 
          Second = 0; 
          Ticks = 638082121800000000L; 
          TimeOfDay = 23:23:00; 
          Year = 2023;}] 
Cuestiones relacionadas