Reputation: 178
Is datetime values with microseconds are converted into double with exact precision?
For eg. i have date as 3 July 2017 10:00:00 00 Ticks 636346728000000050. which converted into double as i am getting as 42919.4166666667. As similarly, i have added the 50 Ticks to current date ie. 3 July 2017 10:00:00 00 Ticks 636346728000000100 which converted into double, also getting same double value but the ticks value has added into date.
I am converted into double by this method date.ToOADate()
can anyone please resolve this ?
Thanks in advance :)
Upvotes: 2
Views: 4185
Reputation: 1
The conversion function ToOADate does not support such small differences. 50 ticks are 50*100ns = 5 μs.
If you check other functions like SystemTimeToVariantTime or VariantTimeToSystemTime, you will find that they are even more restricted, to 1 second precision.
https://www.codeproject.com/Articles/17576/SystemTime-to-VariantTime-with-Milliseconds provides code to allow millisecond precision.
The current resolution for the OLE date is around 629ns, the difference between two doubles with day count (integer part) around 44057 (like today), so everything below 7 Ticks will not make a difference.
One option to calculate an improved OLE date is to convert your ODate back to DateTime, then correct the Ole date based on the Tick difference:
DateTime now = DateTime.Now;
double olenow = now.ToOADate();
DateTime oanow = DateTime.FromOADate(olenow);
double betterolenow = olenow + ((double)(now.Ticks - oanow.Ticks) ) / (24L * 3600 * 1000 * 10000);
Upvotes: 0
Reputation: 1499770
There are two separate logical operations here:
Converting from ticks to microseconds. This is basically a matter of dividing by 10 (there are 100 nanoseconds or 0.1 microseconds in each tick), so that can lose information already in integer arithmetic - but adding 50 ticks is adding exactly 5 microseconds, so that should be okay.
Converting from an integer to a binary floating point number. Your value has 17 significant decimal digits, which is on the higher end of what a 64-bit binary floating point type can represent. You shouldn't rely on more than 15 significant decimal digits.
On top of that, you're using ToOADate
, which appears to have millisecond precision, looking at the reference source.
So:
Ticks
by 10 to get microseconds, only losing a small amount of precisionlong
to double
in a different way, which would lose less information than ToOADate
but you're still going to be losing information in many cases.If you are able to choose a different epoch for your double
value, you could easily express microseconds in values with appropriate precision - but you'd need to know the range of values you need to express in order to check that, as well as having control over the rest of the code using the resulting double
values.
Upvotes: 3
Reputation: 6292
50 ticks cannot be expressed in a OLE Automation date. This code:
DateTime d1 = DateTime.Parse("3 July 2017 10:00:00");
DateTime d2 = d1.AddTicks(100);
double o2 = d2.ToOADate();
Console.WriteLine(o2);
DateTime d3 = d1.AddTicks(1000);
double o3 = d3.ToOADate();
Console.WriteLine(o3);
DateTime d4 = d1.AddTicks(10000);
double o4 = d4.ToOADate();
Console.WriteLine(o4);
generates the output:
42919,4166666667
42919,4166666667
42919,4166666782
so you need at least 10000 ticks for the add to have an impact.
Upvotes: 4