Not allowing a user to put "Clock Out" time < "Clock In" time? - c#

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.

Related

How to subtract two times from two datetime and calculate is elapse time from 61 seconds or not?

I'm working on an asp.net core MVC project. This project about identifying online and offline users, I have two datetime, one of the stores in a database, and another is current datetime, and I must know that time stored in a database elapsed from 61 seconds or not?
I subtract two Datetime and finally use TotalSeconds property.but my output is -22095 or 2319208 and so on.
public void CheckUserStatus()
{
DateTime now = DateTime.Now;
var userTime = _context.Sessions.Where(x => x.LastOnline).Select(x => new {x.LastConnectTime, x.Id});
foreach (var time in userTime)
{
TimeSpan diffrence = now.Subtract(time.LastConnectTime);
int mytime = Convert.ToInt32(diffrence.TotalSeconds);
if ( mytime < 61)
{
Console.WriteLine(time.Id);
}
}
}
I expect out of time base on seconds, for example, right now my output is -22095 or 2319208, and so on but I don't know 2319208 is a regular time or not?
You can easily check that like this :
DateTime now = DateTime.Now;
TimeSpan past = now - now.Subtract(TimeSpan.FromSeconds(60));
TimeSpan post = now - now.Subtract(TimeSpan.FromSeconds(61));
Console.WriteLine(now);
// Should be False: Passed time is less than 60 seconds
Console.WriteLine(past.TotalSeconds > 60);
// Should be True: Passed time is more than 60 seconds
Console.WriteLine(post.TotalSeconds > 60);

Timer Max interval

Using System.Windows.Form.Timer the interval is an int, which gives a maximum interval limit of around 25 days. I know I could create some arbitrary algorithm to start another timer once the limit is reached, but that's just daft.
MISLEADING-IGNORE-->So if I want to set it to around 29 days (2619609112.7228003) milliseconds?<--MISLEADING-IGNORE
EDIT:
The real question here is how can I set System.Windows.Form.Timer to a value higher than maxInt?
The purpose is that I need to set an interval from whenever to the first day of the next month, so it could be 28,29,30 or 31 days, and when that interval expires, calculate the interval to the next first day of the month.
(Basically a Crystal Report is to be run on the 1st day of the month and printed (around 500 pages), because of the length of the reports it is to be run out of hours so it doesn't tie up the printer.)
e.g. run it today (today is 1/12/15), 1/1/16 is next 'first day of the month' so set the interval to the milliseconds between now and then.
1/1/16 comes around so the timer ticks, then calculate and set the interval for 1/2/2016 (the next first day of the month).
#SeeSharp - I did see that question, but I am working on a legacy app and am unsure of the implications of changing the timer, but if I can't get this timer to work I may look at the threading one, thanks.
EDIT2: Thanks for all of your suggestions, I've opted for a 3rd party plugin called FluentScheduler
Set the timer interval to one day (say) and use it to count the number of days up to 29.
Edit
Set the timer to half a day (say) and use it to check that the date is the first of the month.
How about a Month timer - This will fire close to midnight when the month changes. May be that suits your requirement better ?
If we have to consider day-light saving too, then perhaps the timer should fire at 2:00 AM on the 1st day of month so I'll make it configurable.
Here is a code to explain my idea -
public class MonthTimer : IDisposable
{
public event EventHandler<MonthChangedEventArgs> MonthChanged;
DateTime mLastTimerDate;
Timer mTimer;
public MonthTimer(TimeSpan timeOfFirstDay)
: this(DateTime.Now, timeOfFirstDay)
{
}
public MonthTimer(DateTime currentDate, TimeSpan timeOfFirstDay)
{
mLastTimerDate = currentDate.Date;
var milliSecondsInDay = new TimeSpan(1, 0, 0, 0).TotalMilliseconds;
Contract.Assert(timeOfFirstDay.TotalMilliseconds <= milliSecondsInDay); // time within 1st day of month
DateTime currentDateLastSecond = currentDate.Date.AddDays(1).AddTicks(-1); // one tick before midnight
TimeSpan timeSpanInCurrentDate = currentDateLastSecond.Subtract(currentDate); // remaining time till today ends
// I want the timer to check every day at specifed time (as in timeOfFirstDay) if the month has changed
// therefore at first I would like timer's timeout to be until the same time, following day
var milliSecondsTillTomorrow = (timeSpanInCurrentDate + timeOfFirstDay).TotalMilliseconds;
// since out milliseconds will never exceed - . Its okay to convert them to int32
mTimer = new Timer(TimerTick, null, Convert.ToInt32(milliSecondsTillTomorrow), Convert.ToInt32(milliSecondsInDay));
}
private void TimerTick(object state)
{
if(DateTime.Now.Month != mLastTimerDate.Month)
{
if (MonthChanged != null)
MonthChanged(this, new MonthChangedEventArgs(mLastTimerDate, DateTime.Now.Date));
}
mLastTimerDate = DateTime.Now.Date;
}
public void Dispose()
{
mTimer.Dispose();
}
}
public class MonthChangedEventArgs : EventArgs
{
public MonthChangedEventArgs(DateTime previousMonth, DateTime currentMonth)
{
CurrentMonth = currentMonth;
PreviousMonth = previousMonth;
}
public DateTime CurrentMonth
{
get;
private set;
}
public DateTime PreviousMonth
{
get;
private set;
}
}
client code
// Check the new month around 2 AM on 1st day
mMonthTimer = new MonthTimer(new TimeSpan(2, 0, 0));
mMonthTimer.MonthChanged += mMonthTimer_MonthChanged;
One thing I'm not using System.Threading.Timer, therefor the even handler will be called on a separate thread & not UI thread as incase of System.Windows.Forms.Timer if this is an issue in yr case do let me know.
Also do write me a comment if it serves yr purpose or any if any issues
Try Microsoft's Reactive Framework (NuGet "Rx-Main").
You can write this:
Observable
.Timer(DateTimeOffset.Now.AddDays(29.0))
.Subscribe(x =>
{
/* 29 Days Later */
});

Calculate timespan between 2300 and 0100

I wonder how I can get the duration between 2300 and 0100, which should be 0200, but it returns 2200. Im working on an application with Xamarin.Forms and use two TimePickers which returns a TimeSpan.
private TimeSpan CalculateDuration()
{
var result = timePickerEnd.Time.Subtract(timePickerStart.Time);
return result.Duration();
}
As long as the startTime is smaller then the endTime, everything works fine. But if someone starts something at 2300 and ends at 0100 it returns 22. I wonder if anyone have some guidelines how i should attack this problem.
You have specific rules, you have to implement them:
var ts1 = timePickerStart.Time;
var ts2 = timePickerEnd.Time;
var difference= ts2.Subtract(ts1);
if(ts1 > ts2)
{
difference= difference.Add(TimeSpan.FromHours(24));
}
return difference;
Because the rule that you've failed to articulate (that I've guessed at above) is that "if the start time is greater than the end time, then they should be interpreted as occurring on successive days" - which is by no means a universal assumption that the system should make.

How to specify the time precision for a comparison

I have two date values that are being returned, I then need to compare these to ensure lastWriteDate of the file has not been updated since caching.
The problem I've got is, the lastWriteDate has the milliseconds included, and the clientDate doesn't. So when compared, the lastWriteDate will always be greater if it is in the same second.
if (!(Request.Headers["If-Modified-Since"] == null))
{
DateTime clientDate = Convert.ToDateTime(Request.Headers["If-Modified-Since"]);
DateTime lastWriteDate = System.IO.File.GetLastWriteTime(newImagePath);
if (lastWriteDate <= clientDate)
{
//Code here not being reached
}
}
Those miliseconds aren't important for the comparison I'm making, so what would be the best way to compare these values without them?
Subtract one date from the other. THen you will end up with a TimeSpan object, of which you can simply check the number of seconds and ignore the milliseconds.
You can truncate the milliseconds in this way:
if (lastWriteDate.AddMilliseconds(-lastWriteDate.Millisecond) <= clientDate)
{
// ....
}
You could also create a TimeSpan and check if it's lower than your maximum:
TimeSpan diff = clientDate - lastWriteDate;
if (diff < TimeSpan.FromSeconds(1))
{
// ....
}

Calculating how many minutes there are between two times

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;

Categories

Resources