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.