13

i want to have a time stamp for logs on a Windows Mobile project. The accuracy must be in the range a hundred milliseconds at least.

However my call to DateTime.Now returns a DateTime object with the Millisecond property set to zero. Also the Ticks property is rounded accordingly.

How to get better time accuracy?
Remember, that my code runs on on the Compact Framework, version 3.5. I use a HTC touch Pro 2 device.

Based on the answer from MusiGenesis i have created the following class which solved this problem:

/// <summary>
/// A more precisely implementation of some DateTime properties on mobile devices.
/// </summary>
/// <devdoc>Tested on a HTC Touch Pro2.</devdoc>
public static class DateTimePrecisely
{
    /// <summary>
    /// Remembers the start time when this model was created.
    /// </summary>
    private static DateTime _start = DateTime.Now;
    /// <summary>
    /// Remembers the system uptime ticks when this model was created. This
    /// serves as a more precise time provider as DateTime.Now can do.
    /// </summary>
    private static int _startTick = Environment.TickCount;

    /// <summary>
    /// Gets a DateTime object that is set exactly to the current date and time on this computer, expressed as the local time.
    /// </summary>
    /// <returns></returns>
    public static DateTime Now
    {
        get
        {
            return _start.AddMilliseconds(Environment.TickCount - _startTick);
        }
    }
}
spoulson
  • 21,335
  • 15
  • 77
  • 102
Marcel
  • 15,039
  • 20
  • 92
  • 150
  • 2
    No need to retitle your question with "[SOLVED]". You can tell that the question has an accepted answer by the yellow answer counter on the front page or search results. – spoulson Apr 09 '10 at 13:56
  • 2
    As the source of this, I should mention that this class will almost certainly "drift" away from the value returned by regular `DateTime.Now`, possibly by as much as a few seconds (or even lots more) over the course of a day. You can test this quite simply by setting your class' _start property, waiting some length of time (a day or whatever) and comparing `DateTime.Now` to `DateTimePrecisely.Now`. – MusiGenesis Apr 09 '10 at 15:25
  • 1
    If you find the drift amount unacceptable, you can add a `Reset` method which gets fresh values for `_start` and `_startTick`, and call it periodically. This will keep it in long-term sync with the system clock while still giving you (allegedly) millisecond resolution. Or use `ctacke`'s code. – MusiGenesis Apr 09 '10 at 15:27
  • 1
    Yeah, the drift is highly dependent on how the OEM did the clock in hardware, the processor and the crystal used. I've seen bad (nearly a mintue a day drift) and good (10's of ms a day). Without a separate RTC, that's hard to completely get rid of. – ctacke Apr 09 '10 at 15:49
  • 1
    @ctacke: even `System.Diagnostics.Stopwatch` running on PCs (mine, at least) has this level of drift (about 5 seconds a day on my laptop). – MusiGenesis Apr 09 '10 at 15:53
  • 1
    PC crystals are notoriously cheap (and therefore inaccurate). – ctacke Apr 09 '10 at 16:03
  • Thanks to all you commenters. However, I can live with theinacurracies, because I mostly need the monotonically increasing log timestamps over a short period of time (less than an hour typically) so this is ok for me. – Marcel Apr 09 '10 at 20:58
  • Supposing somebody still uses CF on Windows CE, like me, I suggest you don't use the `Environment.TickCount` based approach, because it might loose precision really quicly. On the ARM embedded system, I was developing for the `DateTimePrecisely.Now` was ahead of the system time with more than a minute in less than an hour. On my laptop, it became to be late with several seconds in half a day. I am pretty sure, that `TickCount` is calculated and thus rounded, and as a consequence, not precise. And this will accumulates over time. – ZorgoZ Jan 09 '18 at 07:08

4 Answers4

14

Environment.TickCount will return the number of milliseconds that Windows (or Windows Mobile) has been running since the last reboot.

To use this, add these two form-level variables to your code:

private DateTime _start;
private int _startTick;

In your form's Load event, do this:

private void Form1_Load(object sender, EventArgs e)
{
    _start = DateTime.Now;
    _startTick = Environment.TickCount;
}

Whenever you need a DateTime object with milliseconds, do this:

DateTime timeStamp = 
    _start.AddMilliseconds(Environment.TickCount - _startTick);

Environment.TickCount is an int and this value will "wrap around" to Int32.MinValue after 25 days or so. If your device is going to be running that long without restarting, you'll want to add a check for an Environment.TickCount value that is less than the last value read, and reset both _start and _startTick if so.

MusiGenesis
  • 74,184
  • 40
  • 190
  • 334
  • +1. this did the trick. Too bad that microsoft (or HTC?) does not do this in their code. – Marcel Apr 09 '10 at 10:14
  • 3
    It's HTC's failure, not Microsoft's. It's up to the OEM to provide the OS with a time. – ctacke Apr 09 '10 at 13:54
  • Please help me out as I dont see, how it will return time with more accurancy. You will have "more digits", but thats all, because the starting time already does not contains fractial parts of seconds, so you are just adding "imaginary" numbers. If it is used in log, you can see the ellapsed time between log entries, but can not compare to other systems time. – HoGo Nov 08 '16 at 08:49
2

What about the High Resolution Timer?

Oliver
  • 43,366
  • 8
  • 94
  • 151
1

The main alternative is the System.Diagnostics.Stopwatch class.

It is available in CE but note the IsHighResolution property. It probably is False on your device but do check.

It is as accurate as you're going to get without P/Invoke.

H H
  • 263,252
  • 30
  • 330
  • 514
-3

In regular framework v2.0 you may use DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff") to get miliseconds. More f means more precision.

Nime Cloud
  • 6,162
  • 14
  • 43
  • 75