i need to measure time between 2 button press
in Windows-CE C#
how do do it ?
thank's in advance
DateTime.Now may not be precise enough for your needs. Link (Short short version: DateTime is extremely precise, DateTime.Now -> not so much.)
If you want better precision, use the Stopwatch class (System.Diagnostics.Stopwatch).
Stopwatch watch = new Stopwatch();
watch.Start();
// ...
watch.Stop();
long ticks = watch.ElapsedTicks;
Define a variable when the button is clicked once to NOW().
When you click a second time, measure the difference between NOW and your variable.
By doing NOW - a DateTime variable, you get a TimeSpan variable.
DateTime? time;
buttonClick(....)
{
if (time.HasValue)
{
TimeSpan diff = DateTime.Now.Subtract(time.Value);
DoSomethingWithDiff(diff);
time = null;
}
else
{
time = DateTime.Now;
}
}
See the static System.Environment.TickCount property.
This number of milliseconds elapsed since the system started, so calling it twice and subtracting the earlier value from the later will give you the elapsed time in milliseconds.
Related
I am attempting to create a timesheet calculator which takes calculates the time an employee works and I am close, with one problem.
As I perform the calculation, I only want hours and minutes to display. I am able to get that done, but that causes an issue. If the employee punches out before a full minute is elapsed, that minute is not included in the calculation.
For example, if an emp punches in at 12:00:30 and punches out at 5:00:29, that last minute is not counted in the calculation, so the time shows as 4:59 instead of 5:00.
How do I get the calculation to be based on the hours and minutes and exclude seconds completely?
This is the code I have:
private void btnPunchOut_Click(object sender, EventArgs e)
{
DateTime stopTime = DateTime.Now;
lblPunchOutTime.Text = stopTime.ToShortTimeString();
TimeSpan timeWorked = new TimeSpan();
timeWorked = stopTime - startTime;
lblTimeWorked.Text = timeWorked.ToString(#"hh\:mm");
}
Use TimeSpan.TotalSeconds perhaps...And then add 30 seconds or more, before you convert it to hours by dividing by 3600.
As in
lblTimeWorked.Text = ((timeWorked.TotalSeconds+30)/3600).ToString("0.00") + " hours";
Use Timespan.TotalHours if you want the hours.
But if you want to be accurate, you should create a separate class dedicated to calculating the hours worked by a staff member. Then you can encapsulate lots of business rules in the dedicated class. Staff have entitlements and overtime, expenses or penalty rates - so this can get complex if done properly.
If you want a calculation that really ignores the seconds, the clearest way to accomplish that is to get rid of the seconds on both the start time and the end time. It might not seem accurate because it allows a difference of one second to become a difference of one minute. But that could still be a valid business rule, that you want to subtract according the the minutes that appeared on the clock rather than the actual elapsed seconds.
In other words,
1:00:01 is adjusted to 1:00:00.
1:00:59 is adjusted to 1:00:00.
1:01:00 is "adjusted" to 1:01:00.
1:01:01 is adjusted to 1:01:00.
You can accomplish that with an extension like this:
public static class TimespanExtensions
{
public static TimeSpan TrimToMinutes(this TimeSpan input)
{
return TimeSpan.FromMinutes(Math.Truncate(input.TotalMinutes));
}
}
(I'm sure there's a more efficient way of truncating the seconds, but at least this is clear.)
Now instead of having to figure out how to calculate the difference while rounding seconds or adding seconds, you just trim the seconds before calculating the difference. Here's a unit test:
[TestMethod]
public void NumberOfMinutesIgnoresSeconds()
{
var startTime = TimeSpan.FromSeconds(59).TrimToMinutes();
var endTime = TimeSpan.FromSeconds(60).TrimToMinutes();
Assert.AreEqual(1, (endTime - startTime).TotalMinutes);
}
One Timespan represents 59 seconds, and the next one is 60, or the first second of the next minute. But if you trim the seconds and then calculate the difference you get exactly one minute.
In the context of your code,
DateTime stopTime = DateTime.Now;
lblPunchOutTime.Text = stopTime.ToShortTimeString();
var timeWorked = stopTime.TrimToMinutes() - startTime.TrimToMinutes();
lblTimeWorked.Text = timeWorked.ToString(#"hh\:mm");
I am making a words per minute program (for class) and from what I've been researching, this should work. Basically, if the timer hits 10 seconds, I want the stopwatch to stop (though this is not necessary) and stop the user from typing anymore. How would I achieve this?
public void Timer30()
{
double userCharcount = 0;
string userType;
int timeInSeconds = 10;
//new instance of stopwatch
Stopwatch stopWatch = new Stopwatch( );
//call level 1 words from wordbank
Console.WriteLine(WordBank.LevelOneWords);
stopWatch.Start( );
//**this doesn't seem to work**
if ( stopWatch.Elapsed.Seconds >= timeInSeconds )
{ Console.WriteLine("Time's up! Nice work.");
stopWatch.Stop( );
Console.ReadKey();
}
userType = Console.ReadLine( );
stopWatch.Stop( );
//capture number of characters user types to calculate WPM
userCharcount = userType.Length;
// Get the elapsed time as a TimeSpan value.
TimeSpan ts = stopWatch.Elapsed;
// Format and display the TimeSpan value.
string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}" ,
ts.Hours , ts.Minutes , ts.Seconds ,
ts.Milliseconds / 10);
Console.WriteLine("\nNice job! You finished in " + elapsedTime + "!");
Thread.Sleep(2000);
//CalculateWPMEasy(userCharCount);
}
You can't use Console.ReadLine() in that case, as that doesn't return control to your program until the user has hit Enter. Try using Console.ReadKey() in a loop, where you check that the timeout hasn't expired.
Ok, let's go through what your code does:
Console.WriteLine(WordBank.LevelOneWords);. Ok, you print some words on the console. This statement finishes normally and execution advances to the next statement.
stopWatch.Start( );. Ok, you start the stopwatch. Time starts ticking. Execution advances to the next statement.
if ( stopWatch.Elapsed.Seconds >= timeInSeconds ). Ok, this executes right after you started the stopwatch... a few nanoseconds after, maybe? If timeInSeconds is anything higher than 0, stopWatch.Elapsed.Seconds >= timeInSeconds will be false.
Execution goes on...
How and when did you expect that seconds would go by between steps 2 and 3?
So, how do you fix this? Well the easy way, is to let the user type the words, no matter how slow he might be: userType = Console.ReadLine( );. Only then check the elapsed time and if its greater than timeInSeconds inform the user he was too slow.
I'm calling an update function to draw a real time simulation and was wondering if there was an effective way to get the number of milliseconds passed since the last update? At the moment I have a DispatchTimer calling at regular intervals to update the simulation but the timing isn't accurate enough and ends up being about 60% slower than it should be (it varies).
I would use Stopwatch.GetTimestamp() to get a tick count, then compare the value before and after. You can convert this to timings by:
var startTicks = Stopwatch.GetTimestamp();
// Do stuff
var ticks = Stopwatch.GetTimestamp() - startTicks;
double seconds = ticks / Stopwatch.Frequency;
double milliseconds = (ticks / Stopwatch.Frequency) * 1000;
double nanoseconds = (ticks / Stopwatch.Frequency) * 1000000000;
You could also use var sw = Stopwatch.StartNew(); and sw.Elapsed.TotalMilliseconds afterwards if you just want to time different chunks of code.
Keep a variable that will not reset between calls.
Yours may not need to be static like mine.
private static DateTime _LastLogTime = DateTime.Now;
Then within the method:
// This ensures only the exact one Tick is used for subsequent calculations
// Instead of calling DateTime.Now again and getting different values
DateTime NewTime = DateTime.Now;
TimeSpan ElapsedTime = NewTime - _LastLogTime;
_LastLogTime = NewTime;
string LogMessage = string.Format("{0,7:###.000}", ElapsedTime.TotalSeconds);
I only needed down to the thousandth of a second within my string, but you can get much more accurate with the resulting TimeSpan.
Also there is a .TotalMilliseconds or even .Ticks(the most accurate) value available within the resulting TimeSpan.
I have a datagridview in my application which holds start and finish times. I want to calculate the number of minutes between these two times. So far I have got:
var varFinish = tsTable.Rows[intCellRow]["Finish Time"];
TimeSpan varTime = (DateTime)varFinish - (DateTime)varValue;
int intMinutes = TimeSpan.FromMinutes(varTime);
But the last line won't compile because it says I am using invalid arguments for the Timespan constructor. I've researched quite a bit about how to calculate the number of minutes between two times, but I'm hitting a bit of a brick wall. Can someone please advise me on the best way to achieve my objective.
EDIT/
Now my code is as follows:
var varFinish = tsTable.Rows[intCellRow]["Finish Time"];
TimeSpan varTime = (DateTime)varFinish - (DateTime)varValue;
int intMinutes = (int)varTime.TotalMinutes;
But I am getting an invalid cast on the second line. Both varFinish and varValue are times e.g. 10:00 and 8:00 say. So not sure why they won't cast to type DateTime?
Try this
DateTime startTime = varValue
DateTime endTime = varTime
TimeSpan span = endTime.Subtract ( startTime );
Console.WriteLine( "Time Difference (minutes): " + span.TotalMinutes );
Edit:
If are you trying 'span.Minutes', this will return only the minutes of timespan [0~59], to return sum of all minutes from this interval, just use 'span.TotalMinutes'.
double minutes = varTime.TotalMinutes;
int minutesRounded = (int)Math.Round(varTime.TotalMinutes);
TimeSpan.TotalMinutes: The total number of minutes represented by this instance.
In your quesion code you are using TimeSpan.FromMinutes incorrectly. Please see the MSDN Documentation for TimeSpan.FromMinutes, which gives the following method signature:
public static TimeSpan FromMinutes(double value)
hence, the following code won't compile
var intMinutes = TimeSpan.FromMinutes(varTime); // won't compile
Instead, you can use the TimeSpan.TotalMinutes property to perform this arithmetic. For instance:
TimeSpan varTime = (DateTime)varFinish - (DateTime)varValue;
double fractionalMinutes = varTime.TotalMinutes;
int wholeMinutes = (int)fractionalMinutes;
You just need to query the TotalMinutes property like this varTime.TotalMinutes
If the difference between endTime and startTime is greater than or equal to 60 Minutes , the statement:endTime.Subtract(startTime).Minutes; will always return (minutesDifference % 60). Obviously which is not desired when we are only talking about minutes (not hours here).
Here are some of the ways if you want to get total number of minutes(in different typecasts):
// Default value that is returned is of type *double*
double double_minutes = endTime.Subtract(startTime).TotalMinutes;
int integer_minutes = (int)endTime.Subtract(startTime).TotalMinutes;
long long_minutes = (long)endTime.Subtract(startTime).TotalMinutes;
string string_minutes = (string)endTime.Subtract(startTime).TotalMinutes;
Public void Fee()
{
TimeSpan span1 = TimeSpan.FromHours(dtmIn.Value.Hour);
TimeSpan span2 = TimeSpan.FromHours(dtmOut.Value.Hour);
TimeSpan span3 = TimeSpan.FromMinutes(dtmIn.Value.Minute);
TimeSpan span4 = TimeSpan.FromMinutes(dtmOut.Value.Minute);
TimeSpan span5 = span2.Subtract(span1) + span4.Subtract(span3);
lblTotal.Text = (span5.TotalHours * 3).ToString("$#.00");
}
I do not want the user to be able to be able to clock in during PM and clock out during AM(basically overnight working). Also, not allowing the clock out time being before the clock in time.
You should call new TimeSpan(hours, minutes, seconds: 0) and check whether the in TimeSpan is > the out TimeSpan.
It appears from your code sample that dtmIn and dtmOut are nullable DateTime variables. If so, all you have to do is this:
if (dtmIn.Value >= dtmOut.Value)
{
//'in' time is equal to or greater than 'out' time
... show my error message ...
}
Of course you will need to ensure the DateTime? variables have a value (i.e. do appropriate error checking before using them in the expression).
You probably need to be a little more specific with your logic. Do you mean...
The user should be able to work overnight? If so, that means you need to check to make sure that the date they clocked in is the same as the date they clocked out. `
For example...
if (dtmIn.Value.Date != dtmOut.Value.Date)
{
...
}
The user should not be able to work more than 24 hours? If so, you should subtract the two dates and use the resulting TimeSpan to see how many days they worked.
For example...
if ((dtmOut.Value - dtmIn.Value).TotalDays > 1)
{
...
}
In neither case should you check the time explicitly. For one, if I worked 25 hours then my check out time would still be after the check in time.