Search code examples
f#guard-clause

Pattern match guard with DateTime.TryParseExact?


How to guard with DateTime.TryParseExact (and get the parsed value if possible)? The following code doesn't work.

[<EntryPoint>]
let main args =
    let argList = args |> List.ofSeq
    match argList with
    | "aaa" :: [] -> aaa.main "aaa"
    | "bbb" :: [] -> bbb.main "bbb"
    | "ccc" :: yyyymm :: [] when DateTime.TryParseExact
              (yyyymm, "yyyyMM", CultureInfo.InvariantCulture, DateTimeStyles.None)-> 
        ccc.main "ccc" yyyymm

Solution

  • You can use a mutable:

    let mutable dt = Unchecked.defaultof<_>
    match argList with
    | "ccc" :: yyyymm :: [] when 
        DateTime.TryParseExact(yyyymm, 
                               "yyyyMM", 
                               CultureInfo.InvariantCulture, 
                               DateTimeStyles.None, 
                               &dt) -> ...
    

    But an active pattern makes the match much clearer:

    let (|DateTimeExact|_|) (format: string) s =
        match DateTime.TryParseExact(s, format, CultureInfo.InvariantCulture, DateTimeStyles.None) with
        | true, d -> Some d
        | _ -> None
    
    match argList with
    | "ccc" :: DateTimeExact "yyyyMM" yyyymm :: [] -> ...