Parthiban
Parthiban

Reputation: 178

DateTime in Microseconds

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

Answers (3)

Jürgen Veidt
Jürgen Veidt

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

Jon Skeet
Jon Skeet

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:

  • You could just divide Ticks by 10 to get microseconds, only losing a small amount of precision
  • You could convert from long 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 divide by 10.0 (so avoiding the integer arithmetic to start with) then depending on the value you're trying to represent, you could avoid losing any information.

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

Palle Due
Palle Due

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

Related Questions