1

I currently use a solution for getting a higher resolution timestamp in C# by taking a start time using DateTime.UtcNow and then using a Stopwatch to add ticks to it as time goes by. I came across Stopwatch.GetTimestamp() as a potential alternative or even better solution, but I cannot find reliable information on exactly what this function returns.

Best source of info seems to be this.

GetTimestamp() returns machine-dependent ticks which can be converted into seconds by dividing by the stopwatch frequency. If I do this, I get a value that appears to be a UTC UNIX timestamp which is exactly what I'm after - but I haven't seen anything that states that this is what I should expect from it.

One clue from MSDN states that:

If the Stopwatch class uses a high-resolution performance counter, GetTimestamp returns the current value of that counter. If the Stopwatch class uses the system timer, GetTimestamp returns the current DateTime.Ticks property of the DateTime.Now instance.

Looking then at DateTime.Ticks, we then see:

The value of this property represents the number of 100-nanosecond intervals that have elapsed since 12:00:00 midnight, January 1, 0001 (0:00:00 UTC on January 1, 0001, in the Gregorian calendar), which represents DateTime.MinValue.

I'm therefore not clear how simply dividing some machine-dependent tick-count by the frequency can get me a UNIX 1970+ timestamp? Is it possible that if a high performance timer is not available on the target platform that I might get year 0001-based timestamp instead? Or maybe something else entirely, again depending on the available hi-res timer?

  • Seems like you should be able to just do `(someArbitratyDateTime - epochDateTime).TotalSeconds()` where `epochDateTime` represents January 1, 1970 00:00:00. – itsme86 Jun 15 '16 at 15:28
  • 1
    Take a look at [this question](http://stackoverflow.com/questions/1438652/how-do-i-get-from-stopwatch-gettimestamp-to-a-datetime), then reconsider what you're asking. The time stamp of a stopwatch doesn't necessarily correlate with wall clock time, Unix or otherwise. – Jeroen Mostert Jun 15 '16 at 15:38
  • 1
    [Better question](http://stackoverflow.com/questions/1416139/how-to-get-timestamp-of-tick-precision-in-net-c). There are several good answers here (notably the use of `GetSystemTimePreciseAsFileTime` on recent versions of Windows). This reduces your question to "how do I convert a .NET `DateTime` to a Unix timestamp", which already has an answer. – Jeroen Mostert Jun 15 '16 at 15:42
  • I'm working in Unity so can't make Windows-specific calls or use the latest .NET features. I'll add a Unity tag to this question - I hadn't before because it isn't really a Unity question, although Unity acts as a constraint. @itsme86 - that was my approach previously but I believe it only offers a resolution of 10-15ms. – Sandy MacPherson Jun 15 '16 at 16:41
  • 1
    The question makes very little sense. The Unix timestamp always represents an absolute time, like DateTime does. Stopwatch only ever produces an incremental time, like TimeSpan does. How you are going to convert a time span to a date is something you'll have to think about. – Hans Passant Jun 15 '16 at 16:43
  • My current solution uses the fact that DateTime + TimeSpan = DateTime, or that by combining a high-res stopwatch with a lower-res starting timestamp, I can get better timestamps than if I just used DateTime.UtcNow all the time. I'm not trying to convert a TimeSpan to a DateTime, but rather trying to find out what GetTimestamp() actually does as it sounds like it might be able to produce a higher-res timestamp than UtcNow does. – Sandy MacPherson Jun 15 '16 at 17:29

1 Answers1

0

Can you describe your use case? If you're interested in extra precision, I don't see how you could possibly get it by starting out with DateTime.UtcNow, and then, separately, calling Stopwatch.Start() -- if you add Stopwatch.Elapsed to DateTime.UtcNow, the value is going to be inaccurate, because you have no way of knowing how long after the DateTime.UtcNow call that the stopwatch actually started. If you start the stopwatch first, you have the same problem in reverse.

Generally speaking, in .NET 4.6, there is a ToUnixTimeMilliseconds call on DateTimeOffset that may be helpful (e.g. DateTimeOffset.UtcNow.ToUnixTimeMilliseconds())

Mark Sowul
  • 10,244
  • 1
  • 45
  • 51
  • I'm working in Unity, so don't have access to cutting edge .NET functionality and also can't make calls like GetSystemTimePreciseAsFileTime. I'm trying to timestamp game events as accurately as possible for later comparison to other devices like eye trackers that independently measure these events. Being off by a constant offset is ok and effectively unavoidable. I was hoping that GetTimestamp() would somehow let me avoid doing this UtcNow + Elapsed time calculation. – Sandy MacPherson Jun 15 '16 at 16:36
  • I see. To make it constant, though, you need to do this only once (e.g. at game start). What I'd recommend is creating a new class that does what you want, and have it use the stopwatch as an implementation detail. Then you can implement this logic once, and use the object during the game lifetime as a "replacement" for DateTimeOffset.UtcNow – Mark Sowul Jun 15 '16 at 17:42
  • Thanks - this is pretty much what I've got at the moment. I read that the Elapsed.Ticks value on the stopwatch tends to drift over time which makes taking the UtcNow measurement only once a bit tricky, but given that game play is usually short (under an hour, say), this shouldn't be a problem. – Sandy MacPherson Jun 15 '16 at 17:50