Re: Subtracting DateTimes yields inconsistent results

Tech-Archive recommends: Repair Windows Errors & Optimize Windows Performance



Ken Arway <karway@xxxxxxxxxxxxxx> wrote:
> Jon Skeet [C# MVP] wrote:
>
> > I'm afraid I find your sample quite hard to understand. Could you write
> > a very simple console app which demonstrates the problem? I would
> > imagine it wouldn't need to be more than about 10 lines long. I suspect
> > it's your method of rounding, but it's hard to tell in amongst
> > complicated code.
>
> OK, here's what I'm talking about. This will get the start time, round
> it to the nearest minute, sleep for a minute and a quarter, get the end
> time, round it and subtract the start time from the end time. I see
> that the start and end times are whole minutes only, but the resulting
> TimeSpan is one minute less plus 59sec. 999ms. (Sorry about any word wrap.)

Right. Here's a slightly simpler program which will show what's going
wrong. It doesn't try to round the seconds, it just always rounds down
the milliseconds:

using System;
using System.Threading;

class Test
{
public static void Main()
{
DateTime start = Round(DateTime.Now);

DateTime end = Round(DateTime.Now);
while ((end-start).Milliseconds == 0)
{
Thread.Sleep(10);
end = Round(DateTime.Now);
}

Console.WriteLine (start.ToString("HH:mm:ss.fffffff"));
Console.WriteLine (end.ToString("HH:mm:ss.fffffff"));
}

static DateTime Round(DateTime original)
{
return original.AddMilliseconds(-original.Millisecond);
}
}

This shows not just milliseconds, but microseconds and indeed tenths of
microseconds - ticks, in other words.

You're clearing out the milliseconds, but nothing less than that. At
that point, when you take one time (with 0 microseconds in it) from
another time (with 500 microseconds in it) you end up with a number of
milliseconds which isn't *quite* a multiple of 1000, hence what you're
seeing.

The easiest way to clear it is to change the way you round to use a
DateTime constructor (and for the sake of code readability, please put
it in a method!). Here's one which I believe does what you want it to:

static DateTime Round(DateTime original)
{
return new DateTime (original.Year,
original.Month,
original.Day,
original.Hour,
original.Minute+(original.Second/30));
}

--
Jon Skeet - <skeet@xxxxxxxxx>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
.



Relevant Pages

  • Re: time in us in OnTimer
    ... Windows is completely inappropriate for this purpose. ... you cannot use a general-purpose operating system. ... accuracy of more than a few hundred milliseconds under normal conditions, ... I have, next to my desk, a mass spectrometer that samples every 27 microseconds. ...
    (microsoft.public.vc.mfc)
  • Re: time in us in OnTimer
    ... you cannot use a general-purpose operating system. ... accuracy of more than a few hundred milliseconds under normal conditions, ... microseconds are ... It is handled by internal timing loops in the embedded processor. ...
    (microsoft.public.vc.mfc)
  • Re: time in us in OnTimer
    ... It isn't going to happen in Windows. ... you cannot use a general-purpose operating system. ... accuracy of more than a few hundred milliseconds under normal conditions, ... microseconds are ...
    (microsoft.public.vc.mfc)
  • Re: Line numbering an array
    ... that countis merely accessing a "property" of the array which is set ... that .510 second increment is for a loop ... So using countcosts us .510 microseconds per ... At least 10 milliseconds ...
    (alt.php)
  • Re: Subtracting DateTimes yields inconsistent results
    ... It's not entirely surprising that adding milliseconds doesn't remove ... > the level of ticks) is initialized to zero. ... Will this Round() method return an hour ...
    (microsoft.public.dotnet.languages.csharp)