How to get a UNIX timestamp from Stopwatch.GetTimestamp()? - c#

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?

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())

Related

could DateTime.Ticks value be repeated because culture hour changing

First of all, sorry about my ignorance and my awful english skills, i work to improve them.So here goes my question:
I want use DateTime.Ticks (instead Guid.NewGuid) in order to calculate an identifier and a question is being raised to me. In my current culture we have 2 days on the year when we change the official time: in octuber we add an hour and in april we remove it.
how does it affect to the ticks value? how ticks value is calulated? As far as i understand based on https://msdn.microsoft.com/en-us/library/system.datetime.ticks%28v=vs.110%29.aspx it seems it is not able to be a repeat value because based on the text (...)It does not include the number of ticks that are attributable to leap seconds(...) .
there could be repeated ticks?, (maybe other question would be how long a tick lasts, depends on the computer? )
If i'm not wrong it cant be repeated.
Moreover, Maybe there could be a lot of stuff i misunderstand so i'm really sorry again...
Even without DST changes, you can observe DateTime.Now.Ticks returning the same value multiple times, due to the granularity of the system clock.
But with DST changing, if you use DateTime.Now, you will indeed see the same values repeating for one hour per year. The Ticks property is just "the number of ticks since the DateTime epoch, in whatever kind of value is represented". (A DateTime value can be one of three "kinds" - universal, local, or unspecified. It's all a bit of a mess.)
If you use DateTime.UtcNow you shouldn't see that if your system clock only moves forward... but it's entirely possible for system clocks to be changed, either manually or in an automated way, to correct them for drift. Basically, it's not a good source of uniqueness on its own.
(In terms of the length of a tick - the tick in DateTime is always 100ns. That's not true for Stopwatch, where you need to use the Frequency property to find out how long a tick is, or use the Elapsed property to just find the elapsed time as a TimeSpan.)

Unit of stopwatch.Elapsed property

I am extremely confused with this stopWatch.Elapsed property. It shows the time value in this format
I want to know what should I add in the end of this output. Is it ms (01:20:17.0550410ms) or just s (01:20:17.0550410s)?
And further more if I want to take only the msportion of this output and do some calculation with it which value should I take, is it .0550410 or 55.041? My questions might sound silly but I'm really confused!
please help.
The unit shown is "fractional parts of a second", to the 7th decimal place - i.e. to the 10-millionth of a second.
Since a millisecond is 0.001 seconds, your number of milliseconds is 55.041.
Now, as everyone else said, use stopWatch.Elapsed.TotalMilliseconds (to get all of the milliseconds) or stopWatch.Elapsed.Milliseconds (to get all of the milliseconds less than 1 second).
I am extremely confused with this stopWatch.Elapsed property. It shows the time value in this format
I'll begin at the beginning, just to make sure everything is understood.
Microsoft .Net framework designers have decided that all variables that store information derive from either a Class or a Struct(ture). Both of these base types have some defaults methods. One of these Methods for a ValueType (which I'll discuss below) is .ToString(). When you call the ToString() method on a Windows Runtime structure, it provides the default behavior for value types that don’t override ToString().
I will assuming you are talking about the System.Diagnostics.Stopwatch class. The documentation states:
A Stopwatch instance can measure elapsed time for one interval, or the total of elapsed time across multiple intervals. In a typical Stopwatch scenario, you call the Start method, then eventually call the Stop method, and then you check elapsed time using the Elapsed property.
Before we begin looking at the Properties of the Stopwatch, we need to understand that in order for the Stopwatch to work, there needs to be a way to store a Magnitude of Time (information). A Magnitude of Time in this case a numerical representation of the difference between two points in time; in this case the when the Stopwatch Starts and when the Stopwatch Ends. Microsoft .Net has created a structure called TimeSpan to store this value.
Taking a look at the documentation for the property Stopwatch.Elapsed it is of the type TimeSpan.
Since your screenshot appears to be in a console application, I'll assume the code (which should always be provided but isn't) is the following:
Console.Writeline("Took Time: " + stopWatch.Elapsed.ToString());
This code converts the TimeSpan into a string using the TimeSpan's .ToString() override:
So not passing a value to .ToString() is a null value which defaults to ("c") It's in the TimeSpan Format Strings:
So using your example:
01:20:17.0550410s
It should be obvious that 01 is hours, 20 is minutes, 17 is seconds and .0550410 are tenths of seconds (decisecond). Adding any string values at the end will most likely make no sense because all the numbers are of different time durations. The only way I think it would make sense if you wanted be more specific is to change it to:
01h 20m 17.0550410s
or
01h 20m 17s 055.0410ms
According to the documentation for TimeSpan:
A TimeSpan value can be represented as [-]d.hh:mm:ss.ff, where [...] ss is seconds, and ff is fractions of a second
So in your case, it is 17.0550410 seconds.
Elasped is a TimeSpan, what you're showing is the representation from writing it to the console (Same as calling .ToString() on any non string object), that representation is in hours:minutes:seconds.fraction of second. If you want to show this in a specific amount there are properties for this on the TimeSpan so instead of doing
Console.WriteLine(stopWatch.Elapsed);
You can do
Console.WriteLine(stopWatch.Elapsed.TotalMilliseconds);
A full example to clarify
Console.WriteLine(
"The timer ran for " + stopWatch.Elapsed.Hours + " Hours, "
+ stopWatch.Elapsed.Minutes + " Minutes and "
+ stopWatch.Elapsed.Seconds + ". this amounts to a total of "
+ stopWatch.Elapsed.TotalMilliseconds + " ms" );
It looks like you are just using the default .ToString() method of the Stopwatch.Elapsed property, which actually is a TimeSpan object. You can absolutely control the string formatting of this TimeSpan, as well as use numeric components of it for mathematical operations (rounding, adding, etc.). Please read this: Stopwatch.Elapsed Property
A quick search of 'c# stopwatch' returns the MSDN documentation showing that Stopwatch.Elapsed is a TimeSpan. Then a search on 'c# TimeSpan' returns the MSDN documentation showing that TimeSpan.ToString() returns a string with the following format: [-][d.]hh:mm:ss[.fffffff]. And that's just using google. Next time try doing some research before asking your question.
Assuming that you are interested in StopWatch.Elapsed, then...
In situations like this I find the documentation is often quite helpful.
It states that StopWatch.Elapsed returns
A read-only TimeSpan representing the total elapsed time measured by the current instance.
The documentation for TimeSpan states its many available properties, one of which is Milliseconds and another is TotalMilliseconds. According to the docs:
Milliseconds - Gets the milliseconds component of the time interval represented by the current TimeSpan structure.
whereas
TotalMilliseconds - Gets the value of the current TimeSpan structure expressed in whole and fractional milliseconds.
Other properties allow you to check Days, Hours, Minutes, Seconds etc. Please use the documentation as it saves everyone a lot of time and effort.

Why is DateTime.Now.Subtract(DateTime.UtcNow) not (close to) zero?

If I try:
DateTime.Now.Subtract(DateTime.UtcNow)
I would expect the result to be very close to zero. But it's not, instead it's the time zone difference, in my case, -4 hours. There is a .Kind -- the DateTime KNOWS the timezones are different. Why doesn't it track this for me? Is there a flavor of Subtract that DOES use Kind correctly?
(For reference, a good rundown of what each one outputs can be seen at: https://stackoverflow.com/a/3229429/237091)
Eh? The Kind property does not alter date math. It is only used by time zone methods.
You get exactly the result I would expect you to get. Not sure I understand why you were expecting zero.
There is a .Kind -- the DateTime KNOWS the timezones are different. Why doesn't it track this for me?
Because DateTime is fundamentally broken (and there's more...). IMO it should complain if you try to subtract a value of one kind from another. But no, it just uses the uninterpreted date/time in each value. Very few operations actually take any notice of the Kind, unfortunately. (If you use TimeZoneInfo, those operations do take notice of it.)
Kind was hacked into .NET 2.0; before then a DateTime value didn't even know what kind it was - if you used:
dt = dt.ToLocalTime().ToLocalTime().ToLocalTime();
it would apply the same offset change several times. The BCL team found a couple of spare bits in the binary representation, and used it for Kind.
Basically, I feel your pain. Personally I would prefer it if operations like this threw an exception - subtracting a UTC DateTime from a local DateTime or vice versa makes little sense, IMO.
As an entirely biased plug, you could use Noda Time which separates the ideas of Instant, LocalDate, LocalTime, LocalDateTime, OffsetDateTime and ZonedDateTime, and doesn't let you perform non-sensical arithmetic. Our aim is to provide a saner API than the BCL one. That doesn't necessarily mean we've succeeded, of course :)
Each DateTime object represents a local time (as opposed to a UTC time plus a time zone offset). Even if the Kind property equals UTC, it's just storing the local time at the zero time zone. If it were not a local time, there would be no reason for the UtcNow property.
DateTime does not even store the timezone. If Kind equals UTC, then at least you know it's timezone is zero, but if Kind is local or unspecified, there is no way of knowing the timezone (the Kind property equals Unspecified by default).
Therefore, the Subtract method cannot incorporate the timezone into its calculation because the timezone is unknown.

Recommended method to calculate the difference between two timespans

What should be the best way to calculate the time diff which is accurate upto the level of Microseconds. currently I am doing as follows:
((TimeSpan)(DateTime.Now - _perfClock)).TotalMilliseconds
Note: perfClock is DateTime (set prior to task)
Which is suppose to give accuracy upto Milliseconds, but in my case it is showing values ends with "000". like 8000,9000 etc...
This is forcing me to think that is just converting seconds to Milliseconds somewhere, instead of calculating diff in Milliseconds. (Possibly I am wrong somewhere in code above).
But what should be the recommended mechanism for accurate Time Diff calculation?
-Sumeet
The issue is not with TimeSpan, that is accurate down to ticks, which is 100 nanoseconds.
The issue is you are using DateTime.Now for your timer.
DateTime.Now is accurate to about 16ms i believe. as mentioned by V4Vendetta, you want to use Stopwatch if you need "high resolution" results. Stopwatch can provide you with ticks (long) or TimeSpan. use Timespan for easy manipulation (in your case, add/subtract).
Note also that Stopwatch provides a .IsHighResolution property, to see if you have a better accuracy than Datetime.Now (it's always true on PC iirc)
I don't know the context in which you are measuring time but it would be good to start of with Stopwatch and check your results.
Also worth a read Precise Measurement
Have you tried:
TimeSpan diff = DateTime.Now.Subtract(_perfClock);

Does Daylightsaving time cause DateTime calculations to become negative

We are currently rewritting the core of our services, basically we have scheduled tasks that can run on intervals, dates, specific times etc etc etc.
Currently we're wondering if daylightsaving might cause trouble for us, basically we calculate the next possible runtime, based on what days the task should execute and between what times, and what interval. We do this by taking the current time, and adding days/minutes/hours to this DateTime.
We then take this new run time and subtract DateTime.Now from this DateTime, leaving us with the timespan untill the next run.
How ever, what if the current time is 01:50 on a daylightsavings day, we add 20 minutes, which is our set interval, and end up with a time of 02:10, how ever since this is daylightsavinds, it's actually 01:10.
When i subtract the current time (01:50) from the 01:10 (which is actually 02:10) does this return a negative value which i need to work around or does this never ever return a negative value because DateTime is just a long underneath holding the proper information?
Basically, the following code, is the check needed or not?
//Get interval between nextrun and right now!
double interval = (NextRun - DateTime.Now).TotalMilliseconds;
//Check if interval is ever less or equal to 0, should never happen but maybe with daylight saving time?
if(interval <= 0)
{
//Set default value
interval = IntervalInMilliseconds;
}
We believe that this check isn't needed but our googling so far hasn't given us a definative answer.
Use DateTime.UtcNow instead of DateTime.Now EVERYWHERE
First of all, you can try it yourself as it will help you understand how it works.
Essentially, using your example above, if you have 20 minutes to a local time, it would be 2:10 and not 1:10 as the computation is done in local time. If you want to get 1:10, you need to convert local time to universal time, add 20 minutes and then convert back to local time.
If you want real elapsed time, then you have to convert time to universal time before computing time difference. Also, if you work in local time, you won't be able to differentiate ambiguous time when the clock goes back.

Categories