37

What is the correct way to call DateTime.TryParse from F#? I am trying to test some code from F# interactive and I can't figure out how to pass a mutable DateTime into the second argument by ref. What is the in/out/ref syntax in F#?

This is the method signature I'm looking at: http://msdn.microsoft.com/en-us/library/ch92fbc1.aspx?cs-save-lang=1&cs-lang=fsharp#code-snippet-1

Michael Petrotta
  • 59,888
  • 27
  • 145
  • 179
BuddyJoe
  • 69,735
  • 114
  • 291
  • 466
  • is this a dup: http://stackoverflow.com/questions/4949941/convert-string-to-system-datetime-in-f – Alex Nov 27 '12 at 17:11
  • 5
    See [Passing by Reference](http://msdn.microsoft.com/en-us/library/dd233213.aspx) on MSDN. – Daniel Nov 27 '12 at 17:14

5 Answers5

75

Chris's answer is correct if you really need to pass a mutable DateTime by reference. However, it is much more idiomatic in F# to use the compiler's ability to treat trailing out parameters as tupled return values:

let couldParse, parsedDate = System.DateTime.TryParse("11/27/2012")

Here, the first value is the bool return value, while the second is the assigned out parameter.

kvb
  • 54,864
  • 2
  • 91
  • 133
  • 1
    results will be on of the following tuples: (false, DateTime.MinValue) and (true, DateTime(2012,11,27)) – George Dec 05 '14 at 00:06
14

Here's how to execute DateTime.TryParse in F#:

let mutable dt2 = System.DateTime.Now
let b2 = System.DateTime.TryParse("12-20-04 12:21:00", &dt2)

Where the & operator finds the memory address of dt2 in order to modify the reference.

Here's some additional information on F# parameter syntaxt.

Chris
  • 2,885
  • 18
  • 25
  • 3
    that's not the preferred way, please don't use the mutable dt2 there – Alex Nov 27 '12 at 17:12
  • 2
    @Alex, OP wants to use a mutable DateTime as the second argument. I agree that you can call DateTime.Parse much more cleanly, but that isn't the question that was asked. – Chris Nov 27 '12 at 17:15
10

Just for the sake of completeness, yet another option is to use ref cells, e.g.

let d = ref System.DateTime.MinValue
if (System.DateTime.TryParse("1/1/1", d)) then
   // ...
Marcus
  • 5,987
  • 3
  • 27
  • 40
  • This is better than mutables, as you aren't limited to the current scope. – Ramon Snir Nov 27 '12 at 18:57
  • 1
    Not according to Don Syme (https://github.com/dsyme/fsharp-presentations/blob/master/2018-09-27-openfsharp-code-I-love/fsharp-code-i-love.pptx?raw=true): "We are planning to deprecate “!” and “:=“ to a compat module in F# 4.5 or 5.0" – Anil Jan 28 '19 at 11:10
6

I've found one more way, it seems more functional style (from https://stackoverflow.com/a/4950763/1349649)

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

Unfirtunately, I can't find any information about how it works.

pim
  • 12,019
  • 6
  • 66
  • 69
porfirion
  • 1,619
  • 1
  • 16
  • 23
1

I have a helper module I like to include in all my projects. I collect things like this, putting all the imperative -> functional conversions in one place for reuse:


module helper = 
    
    //if some, unwrap input and call fun
    let inline ( |>- ) x f  = Option.bind f x //bind f x
    //if some, unwrap input, call fun, and wrap output 
    let inline ( |>-+ ) x f = Option.map f x 

    module dateTime =

      let tryParse (input: string) : DateTime option =
        let mutable dt = DateTime.Now
        if DateTime.TryParse(input, &dt) then Some dt else None

EricP
  • 502
  • 2
  • 14