Finding uptime of a program but showing it in MINUTES - c#

So I run some type of game, and I want to add a command !uptime that displays how long server has been running for since the last open or whatever
This code (from microsoft website) shows the tick count and displays it correctly
int result = Environment.TickCount & Int32.MaxValue;
player.SendMessage("Result: " + result);
but I want to be able to display how long its been up in minutes.

From the MSDN documentation, we can see that Environment.TickCount
Gets the number of milliseconds elapsed since the system started.
You can then convert it to minutes like so:
var minutes = (Environment.TickCount - serverStartTickCount) / 60000; // 1000 ms/s * 60 s/m
Alternatively, you might want to consider storing DateTime.Now when the server starts. Say your class is called Program, you can add this to it:
public static readonly DateTime ServerStartTime = DateTime.Now;
and then do this when the command is run:
var uptime = DateTime.Now - Program.ServerStartTime;
var minutes = uptime.TotalMinutes;
This would allow you to get an accurate uptime when the Environment.TickCount roll over every few weeks, as #Carlos pointed out.

From the reference docs:
A 32-bit signed integer containing the amount of time in milliseconds
that has passed since the last time the computer was started.
So divide by 1000 to get seconds, and then 60 to get minutes.
Note the thing is only 32 bit, so it loops back every few weeks.

Use a TimeSpan.
TimeSpan uptime = TimeSpan.FromMilliseconds(Environment.TickCount);
double totalMinutes = uptime.TotalMinutes;

Related

In net code for a C# game, I'm seeing an issue where the system is returning negatives. Can anyone spot why or offer improvements?

The main "Ping"/"Time" function for the game is this:
Net Code For Server - Time/Ping
Outside of the switch, TimeSync() functions like this:
private void TimeSync()
{
YGConnection.Send("Time", DateTime.UtcNow.Millisecond);
}
It sends the current UTCNow.Millisecond time to the server.
Finally, getTime() gets the current time + the offset of the server.
private double getTime()
{
return Math.Round((DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalMilliseconds) + Offset;
}
It all works, but the numbers produced are like this:
Version 0.1.5 : Server time offset: -486335789940 - Ping: -943491433067
The server basically sends getTime() back, but without the offset. I'm wondering what is going on with the negative numbers and if there is anything I can do to fix that.
DateTime.Milliseconds is the number of milliseconds (thousandths of a second) within the current second. If you only compare Milliseconds, you will lose any information like the second it occurred in.
At midnight it is 00:00:00.000
500 milliseconds later it is 00:00:00.500
500 milliseconds later it is 00:00:01.000
If you are just comparing the milliseconds, the difference between the first two times will be 500.
The difference between the last two will be -500.
What you probably want to do is return a whole date/time value rather than just the milliseconds. If you subtract 2 DateTime objects, you get a TimeSpan object. From that you can find the TimeSpan.TotalMilliseconds will give you how many milliseconds there are between those two times regardless of how many seconds have elapsed.

Math.Round problems

I'm trying to create a clock for my game. My hours and seconds are both float values so I am using Math.Round to round them off to the nearest whole number. The problem is that the Hours and Seconds variables aren't changing at all. Am I using Math.Round wrong?
public void Update()
{
Hours = (float)Math.Round(Hours, 0);
ClockTime = Hours + ":" + Seconds;
if (Hours >= 24)
Hours = 0;
if (Seconds >= 60)
Seconds = 0;
}
In my update method for my day/night class.
float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds;
clock.Hours += (float)elapsed;
clock.Update();
When I print the numbers on the screen, nothing is changing. If I take away the (float) cast to the Math.Round I get an error cannot convert double to float.
Don't use floating point in this case, there's absolutely no reason for an hour, minute or second to be non-integral.
What's almost certainly happening is that you're ending up with a float value like 59.9999 despite the fact you think you're rounding it.
There are real dangers in assuming floating point values have more precision than they actually do.
If you hold your number of seconds in an unsigned integral 32-bit type, you can represent elapsed time from now until about the year 2150 AD, should anyone still be playing your game at that point :-)
Then you simply use integer calculations to work out hours and seconds (assuming you're not interested in minutes as seems to be the case), pseudo-code such as:
hours = elapsed_secs / 3600
secs = elapsed_secs % 3600
print hours ":" seconds
Beyond that advice, what you're doing seems a tad strange. You are adding an elapsed seconds field (which I assume you're checked isn't always set to zero) to the hours variable. That's going to make gameplay a little difficult as time speeds by at three and a half thousand times its normal rate.
Actually, you should used DateTime to track your time and use the DateTime properties to get the hours and seconds correctly instead trying it yourself using float for seconds and hours. DateTime is long based and supports from fractions of milliseconds to millenias and of course seconds. It has all the functions built in to add milliseconds or years or seconds or ... correctly, which is actually rather difficult.

Task.Duration Property in ms project

How I have to convert Task.Duration that get valid result?
I find explanations about this property in MSDN:
Gets or sets the duration (in minutes) of a task.
But it doesn't work correct.
If I divided result by 60 (minutes in hour) and 24(hours in day) I get incorrect result.
But if I divided by 20 and 24 all it's ok. And I don't understand why.
I use C# on .Net 3.5 and Office Primary Interop Assemblies ( Microsoft.Office.Interop.MSProject for office 2010).
I use that code :
void SetProperties(MSProject.Task o, string version)
{
Wbs = o.WBS.ToString();
Name = o.Name.ToString();
StartDate = (System.DateTime) o.Start;
FinishDate = (System.DateTime)o.Finish;
Iteration = version;
duration = (Convert.ToInt16(o.Duration)/10/24).ToString();//after result //divided by 2 I get correct result. Why?
}
thanks
The reason that it doesn't work like you expect is because in a day you do not have 24 hours of working time. The Duration of a task is the amount of working time between the start and finish, not the absolute number of hours.
Since the default number of working hours in a day is 8, you divide the total minutes by 480 (60 min * 8 hours) to get the number of days. Your calculation of 20 * 24 just so happens to also equal 480, so you stumbled upon the correct number.
Of course, do not expect that Start + Duration (in days) is going to equal your Finish date. That's because you also have to factor in non-working days, like weekends. So you can have a 3 day task that starts on Friday, and it will not finish until the end of the day on Tuesday (5 calendar days).

DateTime, minutes since update?

I have this DateTime object (update) which is set to DateTime.now, when i update my application.
I also have this timerTick event, called on every 5 seconds which should check how many minutes ago, update was.
I've tried with:
if ((DateTime.Now - Updated).Minutes > 0)
{
updateTextBlock.Text = "updated " + ((DateTime.Now - Updated).Minutes).ToString() + " minutes ago";
}
But it does not seem to work correctly. Isn't there a better way to do this?
/R
I suspect you want TotalMinutes instead of Minutes. Otherwise you'll only ever get a value in the range -59 to 59.
You may also want to consider using UtcNow instead of Now - otherwise you could get odd effects due to time zone changes (either the user changing time zone, or the time zone changing its UTC offset, usually for daylight saving time.)
You may find it easier to use an instance of System.Diagnostics.StopWatch to keep track of how much time has elapsed since any particular starting point.
It can be more reliable and accurate than doing math on DateTime objects because it'll use the hardware's High Resolution Timer if one is available.
You're probably looking for TotalMinutes, not just Minutes. TotalMinutes will give you the total number of minutes in the interval, whereas Minutes only gives 0-59 (since you also have Hours, etc.)
One way I did something similar was using TimeSpan
I had two variables timePassed and tickTime
where I would set tickTime to be a 5 second TimeSpan and timePassed to be 0
TimeSpan tickTime = new TimeSpan(0,0,0,5); // 5 seconds
TimeSpan timePassed = new TimeSpan(0,0,0,0); // 0 seconds
then in the handler for the tick event I would add tickTime to timePassed
timePassed = timePassed.Add(tickTime); \\ adds 5 seconds to the timePassed TimeSpan
Then you can use timePassed to get the time since update.
Hope this helps

.NET QueryPerformanceCounter printing the day time

I need to format the day time using QueryPerformanceCounter Win32 API.
The format, is: HH:mm:ss.ffffff , containing hours minuts seconds and microseconds.
I need to use THIS function, because another process (written in C) is using this function and the purpose is using the same function in both places.
Thanks
The System.Diagnostics.Stopwatch class uses QueryPerformanceCounter(), saves you from having to P/Invoke it.
You should not use QueryPerformanceCounter to determine time of day. It can only be used to determine an elapsed interval with a very high resolution as it returns the number of ticks that passed since the computer was last restarted.
As such, at best, you may only determine how many hours, minutes, and seconds have passed since a previous reading of QueryPerformanceCounter which must not have happened too long in the past.
In order to convert from ticks to seconds you need to determine the frequency (using QueryPerformanceFrequency) of the ticks on the computer you're running the QueryPerformanceCounter function and then divide your reading by that frequency:
// obtain frequency
long freq;
QueryPerformanceFrequency(freq);
// then obtain your first reading
long start_count;
long end_count;
QueryPerformanceCounter(start_count)
// .. do some work
// obatin your second reading
QueryPerformanceCounter(end_count);
// calculate time elapsed
long milliseconds_elapsed = (long)(((double)(end_count - start_count) / freq) * 1000);
// from here on you can format milliseconds_elapsed any way you need to
An alternative to the above example would be to use the TimeSpan structure available in .Net which has a constructor that takes ticks like so:
// then obtain your first reading
long start_count;
long end_count;
QueryPerformanceCounter(start_count)
// .. do some work
// obatin your second reading
QueryPerformanceCounter(end_count);
TimeSpan time_elapsed = new TimeSpan(end_count - start_count);
Console.WriteLine("Time Elapsed: " + time_elapsed.ToString());
Can use :
1) The System.Diagnostics.Stopwatch class uses QueryPerformanceCounter(), saves you from having to P/Invoke it.
2) Can use directly by importing from the Win32 dll . [DLLImport(Win32)] and the name ofthe function
Possibly I misunderstand the question, as for me none of the previous answers are relevant at all.
I had the problem (which sent me here): Given a value from QueryPerformanceCounter, because something out of my control specifies timestamps using that function, how can I convert these values to a normal date / time?
I figured that QueryPerformanceCounter returns the number of seconds since the system booted, multiplied (and extended in resolution) depending on QueryPerformanceFrequency.
Thus, the most simple solution is to get the current date/time, subtract the amount of seconds returned by QueryPerformanceCounter/QueryPerformanceFrequency, and then add the values you like to format as time of day.

Categories