This question is not about whether serializing a DateTime to a double and back is a sensible thing to do but about what to do when this is what you have to do.
The solution on the surface is to use DateTime.ToOADate(), as per Convert DateTime to Double but this loses precision quite badly, e.g.
let now = DateTime.UtcNow in DateTime.FromOADate(now.ToOADate()).Ticks - now.Ticks
results in something like
val it : int64 = -7307L, which is pretty awful as that's almost a millisecond.
A more crude approach (of just converting between long and double (which is called float in F#) is actually somewhat better in this respect:
let now = DateTime.UtcNow in DateTime(int64(float(now.Ticks))).Ticks - now.Ticks
results in something like val it : int64 = -42L -- better, but still not exact. The reasons for loss of precision are discussed, for example, in C#: Double to long conversion.
So the question is: is there a way to round-trip a DateTime into a double and back, without loss of precision?
UPDATE: the accepted answer is clear at explaining how "it actually works", but it turns out that System.BitConverter.Int64BitsToDouble() and System.BitConverter.DoubleToInt64Bits() do more or less that, albeit obviously constrained to long<->double conversions, and on little-endian machines only. See https://referencesource.microsoft.com/#mscorlib/system/bitconverter.cs,db20ea77a561c0ac for the actual code.