Consider the following code that converts a DateTime
to a string
, tries to parse it using the TryParse
method on DateTime
, and returns an DateTime option
indicating whether parsing the string
was successful or not:
let dt = DateTime.Now
printfn "%A" dt
let parseDateTime (str: string) =
match DateTime.TryParse str with
| (true, v) -> Some v
| _ -> None
let parsedDateTime =
dt.ToString () |> parseDateTime
match parsedDateTime with
| Some v ->
printfn "%A" v
assert (v = dt)
| _ -> ()
The assert
statement fails, which I would not expect it to. printfn
prints out the same string to the Console which further puzzles me.
If I change the assert
statement above to assert (v.ToString() = dt.ToString())
the assert
passes as I would have expected when comparing the two DateTime
values.
Is there something that I'm missing here when it comes to DateTime
equality? I've also tested this using int
and Guid
(swapping out DateTime.TryParse
for Int32.TryParse
and Guid.TryParse
respectively) and the assert
passes as I would expect it to when comparing values for equality.
CodePudding user response:
The resolution of a DateTime
value is a single "tick", which represents one ten-millionth of a second. You also need to consider time zone differences. The default output format doesn't include this level of detail. If you want to "round trip" a DateTime
, write it out with ToString("o")
and then use DateTimeStyles.RoundtripKind
when parsing:
open System
open System.Globalization
let parseDateTime (str: string) =
match DateTime.TryParse(str, null, DateTimeStyles.RoundtripKind) with
| (true, v) -> Some v
| _ -> None
let parsedDateTime =
dt.ToString ("o") |> parseDateTime // e.g. "2021-11-15T15:36:07.6506924-05:00"