Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get timestamp of tick precision in .NET / C#?

Tags:

c#

.net

timestamp

People also ask

What is DateTime now ticks in C#?

If the DateTime object has its Kind property set to Unspecified , its ticks represent the time elapsed time since 12:00:00 midnight, January 1, 0001 in the unknown time zone. In general, the ticks represent the time according to the time zone specified by the Kind property.

What is a tick time unit?

A tick is 100 nanoseconds, and is the unit used for the Tick property of DateTime. That's it.

How precise is DateTime now?

From MSDN you'll find that DateTime. Now has an approximate resolution of 10 milliseconds on all NT operating systems. The actual precision is hardware dependent.

How do you convert ticks to seconds?

Minecraft game ticks are 20 ticks to 1 second, that means you can simply multiply 20 to 516, and the answer is 10320 ticks.


The value of the system clock that DateTime.Now reads is only updated every 15 ms or so (or 10 ms on some systems), which is why the times are quantized around those intervals. There is an additional quantization effect that results from the fact that your code is running in a multithreaded OS, and thus there are stretches where your application is not "alive" and is thus not measuring the real current time.

Since you're looking for an ultra-accurate time stamp value (as opposed to just timing an arbitrary duration), the Stopwatch class by itself will not do what you need. I think you would have to do this yourself with a sort of DateTime/Stopwatch hybrid. When your application starts, you would store the current DateTime.UtcNow value (i.e. the crude-resolution time when your application starts) and then also start a Stopwatch object, like this:

DateTime _starttime = DateTime.UtcNow;
Stopwatch _stopwatch = Stopwatch.StartNew();

Then, whenever you need a high-resolution DateTime value, you would get it like this:

DateTime highresDT = _starttime.AddTicks(_stopwatch.Elapsed.Ticks);

You also may want to periodically reset _starttime and _stopwatch, to keep the resulting time from getting too far out of sync with the system time (although I'm not sure this would actually happen, and it would take a long time to happen anyway).

Update: since it appears that Stopwatch does get out of sync with the system time (by as much as half a second per hour), I think it makes sense to reset the hybrid DateTime class based on the amount of time that passes between calls to check the time:

public class HiResDateTime
{
    private static DateTime _startTime;
    private static Stopwatch _stopWatch = null;
    private static TimeSpan _maxIdle = 
        TimeSpan.FromSeconds(10);

    public static DateTime UtcNow
    {
        get
        {
            if ((_stopWatch == null) || 
                (_startTime.Add(_maxIdle) < DateTime.UtcNow))
            {
                Reset();
            }
            return _startTime.AddTicks(_stopWatch.Elapsed.Ticks);
        }
    }

    private static void Reset()
    {
        _startTime = DateTime.UtcNow;
        _stopWatch = Stopwatch.StartNew();
    }
}

If you reset the hybrid timer at some regular interval (say every hour or something), you run the risk of setting the time back before the last read time, kind of like a miniature Daylight Savings Time problem.


To get a high-resolution tick-count, please, use the static Stopwatch.GetTimestamp()-method:

long tickCount = System.Diagnostics.Stopwatch.GetTimestamp();
DateTime highResDateTime = new DateTime(tickCount);

just take a look at the .NET Source Code:

    public static long GetTimestamp() {
        if(IsHighResolution) {
            long timestamp = 0;    
            SafeNativeMethods.QueryPerformanceCounter(out timestamp);
            return timestamp;
        }
        else {
            return DateTime.UtcNow.Ticks;
        }   
    }

Source Code here: http://referencesource.microsoft.com/#System/services/monitoring/system/diagnosticts/Stopwatch.cs,69c6c3137e12dab4


[The accepted answer does not appear to be thread safe, and by its own admission can go backwards in time causing duplicate timestamps, hence this alternative answer]

If what you really care about (per your comment) is in fact, a unique timestamp that is allocated in strict ascending order and which corresponds as closely as possible to the system time, you could try this alternative approach:

public class HiResDateTime
{
   private static long lastTimeStamp = DateTime.UtcNow.Ticks;
   public static long UtcNowTicks
   {
       get
       {
           long orig, newval;
           do
           {
               orig = lastTimeStamp;
               long now = DateTime.UtcNow.Ticks;
               newval = Math.Max(now, orig + 1);
           } while (Interlocked.CompareExchange
                        (ref lastTimeStamp, newval, orig) != orig);

           return newval;
       }
   }
}

These suggestions all look too hard! If you're on Windows 8 or Server 2012 or higher, use GetSystemTimePreciseAsFileTime as follows:

[DllImport("Kernel32.dll", CallingConvention = CallingConvention.Winapi)]
static extern void GetSystemTimePreciseAsFileTime(out long filetime);

public DateTimeOffset GetNow()
{
    long fileTime;
    GetSystemTimePreciseAsFileTime(out fileTime);
    return DateTimeOffset.FromFileTime(fileTime);
}

This has much, much better accuracy than DateTime.Now without any effort.

See MSDN for more info: http://msdn.microsoft.com/en-us/library/windows/desktop/hh706895(v=vs.85).aspx


It does return the most accurate date and time known to the operating system.

The operating system also provides higher resolution timing through QueryPerformanceCounter and QueryPerformanceFrequency (.NET Stopwatch class). These let you time an interval but do not give you date and time of day. You might argue that these would be able to give you a very accurate time and day, but I am not sure how badly they skew over a long interval.


1). If you need high resolution absolute accuracy: you can't use DateTime.Now when it is based on a clock with a 15 ms interval (unless it is possible "slide" the phase).

Instead, an external source of better resolution absolute accuracy time (e.g. ntp), t1 below, could be combined with the high resolution timer (StopWatch / QueryPerformanceCounter).


2). If you just need high resolution:

Sample DateTime.Now (t1) once together with a value from the high resolution timer (StopWatch / QueryPerformanceCounter) (tt0).

If the current value of the high resolution timer is tt then the current time, t, is:

t = t1 + (tt - tt0)

3). An alternative could be to disentangle absolute time and order of the financial events: one value for absolute time (15 ms resolution, possibly off by several minutes) and one value for the order (for example, incrementing a value by one each time and store that). The start value for the order can be based on some system global value or be derived from the absolute time when the application starts.

This solution would be more robust as it is not dependent on the underlying hardware implementation of the clocks/timers (that may vary betweens systems).