Environment.TickCount vs DateTime.Now
Use Stopwatch class. There is a decent example on msdn: http://msdn.microsoft.com/en-us/library/system.diagnostics.stopwatch.aspx
Stopwatch stopWatch = Stopwatch.StartNew();
Thread.Sleep(10000);
stopWatch.Stop();
// Get the elapsed time as a TimeSpan value.
TimeSpan ts = stopWatch.Elapsed;
How Environment.TickCount overflows after 25 days (or 48-49 days)
For starters, TickCount
returns milliseconds, not ticks in the sense of DateTime.Ticks
. It does so with a precision the same as the system timer, which is about 10-16 milliseconds.
The documentation explains how the value cycles:
Because the value of the TickCount property value is a 32-bit signed integer, if the system runs continuously, TickCount will increment from zero to Int32.MaxValue for approximately 24.9 days, then jump to Int32.MinValue, which is a negative number, then increment back to zero during the next 24.9 days. You can work around this issue by calling the Windows GetTickCount function, which resets to zero after approximately 49.7 days, or by calling the GetTickCount64 function.
Doing the maths, we find out that 24.9 days is 2,151,360,000 (compared to Int.MaxValue
of 2,147,483,647). MaxValue + |MinValue|
yields 4294967295
, which if divided by 86400000 milliseconds (1 day) yields about 49.7 days, as the documentation suggests.
Source
DateTime from TickCount?
You can't, without more information (and even then it can be ambiguous). Environment.TickCount
returns:
A 32-bit signed integer containing the amount of time in milliseconds that has passed since the last time the computer was started.
... so unless you can find out the time the computer was started from somewhere, you're out of luck. There may well be registry entries or system calls you can make to find out the last boot time, but I don't know them off the top of my head. Of course, you can get an approximate value by taking Environment.TickCount
yourself and DateTime.UtcNow
as soon after (or before) that as possible, and finding the difference between the two:
public static DateTime UnreliableDateTimeFromTickCount(int tickCount)
{
DateTime now = DateTime.UtcNow;
DateTime boot = now - TimeSpan.FromMilliseconds(Environment.TickCount);
return boot + TimeSpan.FromMilliseconds(tickCount);
}
However, even with that, the value will cycle round every 24.9 days, so if the computer has been on for longer than that, the count is ambiguous.
I'd suggest avoiding using Environment.TickCount
if possible, basically - is this under your control at all?
Environment.TickCount is not enough
public void BootTime(){
SelectQuery query = new SelectQuery("SELECT LastBootUpTime FROM Win32_OperatingSystem WHERE Primary='true'");
ManagementObjectSearcher searcher = new ManagementObjectSearcher(query);
foreach (ManagementObject mo in searcher.Get())
{
DateTime dtBootTime = ManagementDateTimeConverter.ToDateTime(mo.Properties["LastBootUpTime"].Value.ToString());
Console.WriteLine(dtBootTime.ToString());
}
}
Is Environment.TickCount affected by system time adjustments?
No, Environment.TickCount
is not affected by adjustments of the system time. That was my interpretation of the documentation, but my curiosity demanded harder proof, so I had the following code run while adjusting the system back and forth one hour:
while (true)
{
Console.WriteLine(Environment.TickCount);
Thread.Sleep(1000);
}
...and the output showed a perfect sequence that was not affected by the time adjustments.
Update
So I did some more homework, triggered by Marcus' question in the comments below. I am quite sure (could not confirm though) that Environment.TickCount makes a call to GetTickCount
that has the following mentioned in the docs:
The resolution of the GetTickCount
function is limited to the resolution
of the system timer, which is
typically in the range of 10
milliseconds to 16 milliseconds. The
resolution of the GetTickCount
function is also affected by
adjustments made by the
GetSystemTimeAdjustment function.
So, while it is not affected by altering the system time, it seems that will be affected by adjustments that are caused by a call to SetSystemTimeAdjustment
.
Should I make a wrapper class for Environment.TickCount?
While I think it is duplicate of discussion on TickCount vs. Now...
Is TickCount the best tool you need to decide yourself. If 100ms matters for 1 million of operations you plan to measure - probably, but I strongly doubt as precision of TickCount is 10ms your average error for that many measurements would be about 5ms*10^6.
I think you should create wrapper class for your time measurement, but mainly not to protect from wraparound, but to allow unit testing of your code. It is not easy to mock system-wide time functions, but custom class can be setup for ease of use and testing.
How many ways are there to measure time?
What's up with that?
The first sentence of each of the documentation pages you link to give a pretty clear description of their purpose (emphasis added):
DateTime.Now
the current date and time on this computer, expressed as the local time.
Environment.TickCount
Gets the number of milliseconds elapsed since the system started.
StopWatch
Provides a set of methods and properties that you can use to accurately measure elapsed time.
DateTime
Represents an instant in time, typically expressed as a date and time of day.
TimeSpan
Represents a time interval.
(a difference between two points in time)
So DateTime
and TimeSpan
are not interchangeable, and more than Location
and Distance
are. They are related but represent different things.
If any of those are not clear, or you need further clarification, please say specifically what you're confused about.
Also, the definition of "Tick" seems to be inconsistent.
Because they're define _within the context of where they're defined. There's not an "industry-standard" definition for "ticks" that I'm aware of. Some types (like Stopwatch
) sacrifice range for greater precision, while others (like DateTime
) allow for much larger ranges but cannot be millisecond-precise.
Are there any others?
One that you haven't mentioned is:
Timer
Generates an event after a set interval, with an option to generate recurring events.
Again, it serves a different purpose. It's designed to do something at regular intervals.
I'm not sure how broad your scope is to know if there are "any others". If you have a specific need that isn't met by one of these classes then add that to your question.
Related Topics
How to Use Jwt in MVC Application for Authentication and Authorization
How to Get Memcached Running on a Windows (X64) 64Bit Environment
Binding Wpf Datagrid Cell Background Colour with Trigger
How to Flatten an Expandoobject Returned via JSONresult in ASP.NET MVC
How Does Creating a Instance of Class Inside of the Class Itself Works
How to Post Using Httpclient Content Type = Application/X-Www-Form-Urlencoded
How to Detect Keypress While Not Focused
Read Fixed Width Record from Text File
Establish a Link Between Two Lists in Linq to Entities Where Clause
To Return Iqueryable<T> or Not Return Iqueryable<T>
When Do We Need to Set Processstartinfo.Useshellexecute to True
C++/Cli Wrapper for Native C++ to Use as Reference in C#
HTML Table (Text) to Image Using C#
Asp.Net-Mvc: Razor '@' Symbol in Js File
Posting JSON to Url via Webclient in C#
How to Tell JSON.Net Globally to Apply the Stringenumconverter to All Enums
Selenium Error - the Http Request to the Remote Webdriver Timed Out After 60 Seconds