Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TimeSpan FromMilliseconds strange implementation?

Tags:

c#

.net

timespan

I recently encountered some weird behaviour in the .NET TimeSpan implementation.

TimeSpan test = TimeSpan.FromMilliseconds(0.5);
double ms = test.TotalMilliseconds; // Returns 0

FromMilliseconds takes a double as parameter. However, it seems the value is rounded internally.

If I instantiate a new TimeSpan with 5000 ticks (.5 ms), the value of TotalMilliseconds is correct.

Looking at the TimeSpan implementation in reflector reveals that the input is in fact casted to a long.

Why did Microsoft design the FromMilliseconds method to take a double a parameter instead of a long (since a double value is useless given this implementation)?

like image 961
DEHAAS Avatar asked Mar 27 '11 16:03

DEHAAS


3 Answers

The first consideration is wondering why they selected a double as the return value. Using long would have been an obvious choice. Although there already is a perfectly good property that is long, Ticks is unambiguous with a unit of 100 nanoseconds. But they picked double, probably with the intention to return a fractional value.

That however created a new problem, one that was possibly only discovered later. A double can store only 15 significant digits. A TimeSpan can store 10,000 years. It is very desirable to convert from TimeSpan to milliseconds, then back to TimeSpan and get the same value.

That isn't possible with a double. Doing the math: 10,000 years is roughly 10000 x 365.4 x 24 x 3600 x 1000 = 315,705,600,000,000 milliseconds. Count off 15 digits, best a double can do, and you get exactly one millisecond as the smallest unit that can still be stored without round-off error. Any extra digits will be random noise.

Stuck between a rock and a hard place, the designers (testers?) had to choose between rounding the value when converting from TimeSpan to milliseconds. Or to do it later when going from milliseconds to TimeSpan. They chose to do it early, a courageous decision.

Solve your problem by using the Ticks property and multiplying by 1E-4 to get milliseconds.

like image 99
Hans Passant Avatar answered Nov 18 '22 21:11

Hans Passant


This is by design, obviously. The documentation says as much:

The value parameter is converted to ticks, and that number of ticks is used to initialize the new TimeSpan. Therefore, value will only be considered accurate to the nearest millisecond.

like image 41
CodeNaked Avatar answered Nov 18 '22 20:11

CodeNaked


Accepting a double is a logical design. You can have fractions of milliseconds.

What's happening internally is an implementation design. Even if all current implementations (of the CLI) round it first that doesn't have to be the case in the future.

like image 2
Henk Holterman Avatar answered Nov 18 '22 22:11

Henk Holterman