How to make my calculation more accurate - c#

I work on a calculator when I try to receive precisely the amount of vacation used for one single month.
This works perfectly when I book a hole day . But if I want to a some hours or just a 1/2 it is "not working" it is displayed as a whole day.
How can I make my calculation more precise ?
public double[] GetMonthReport(int year)
{
double[] yearMonths = new double[13];
if (this.HtVacationDays.Any())
{
}
{
foreach (ZvVacationDay vacationDay in this.ZvVacationDay)
{
foreach (DateTime vacationDayDate in vacationDay.GetDates())
{
if (vacationDayDate.Year == year)
{
yearMonths[vacationDayDate.Month] += 1;
}
}
}
}
return yearMonths;
}
In my ZvVacationDay I have FromDate (datetime) and a ToDate(datetime) and also a title as varchar etc...
Here is a example for my data in the db. now for a "whole" day of vacation
FromDate 2009-08-17 08:00:00:000 ToDate 2009-08-17 16:00:00:000
Thanks for help and fast answer !

The pseudo-code would be:
if (vacationDayDate.Year == year)
{
if({isHalfDay})
yearMonths[vacationDayDate.Month] += 0.5;
else // is full day
yearMonths[vacationDayDate.Month]++;
}
Or more succinctly:
if (vacationDayDate.Year == year)
{
yearMonths[vacationDayDate.Month] += {isHalfDay} ? 0.5 : 1.0;
}

You would need to know how much time they took off.
You could either store Days off as a number of hours/part days off so your iteration becomes
foreach(TimeSpan vacationTimeOff in vacationDay.GetTimeOff())
or have a RAHalfVacationDays and iterate over that.
As soon as you have the partial days as a datasource it becomes trivial
yearMonths[vacationDayDate.Month] += timeOff;

Related

How to find given Event datetime is past event or Future event while considering hours aslo

I have Events page, In that displaying past present and future events counts and list. Here I'm facing a issue form QA team.
Example:
**Event date** is : 2022-01-20 08:00:00.000
**Current datetime** is: 2022-01-20 10:00:00.000
now based on above dates , we need to display event as past event because of two hours less than the Current datetime
if (planEvents.Count > 0)
{
switch (statusID)
{
case (int)GenericEnum.EventStatus.TodaysEvents:
events = planEvents.Where(o => o.EventDate.Date == DateTime.Today.Date).Skip(startIndex - 1).Take(pageSize).ToList();
totalCount = planEvents.Where(o => o.EventDate.Date == DateTime.Today.Date).ToList().Count();
break;
}
}
I tried above code but it's only returning date matching records but not hours comparison. can any once please help me.
First off, you should probably use UTC for all times, but that's a different issue. I don't really understand the use case you're after, but you can use the current time and add or subtract time units to create a range start and end. Not tested, but you should have something like this to select from a date range:
var start = DateTime.Now.AddHours(-2); // start from 2 hours ago
var end = DateTime.Now.AddHours(2); // end 2 hours from now
events = planEvents.Where(x => x.EventDate > start && x.EventDate < end);
Considering present events are the one falls within the current hour. Not tested, but it should work
if (planEvents.Any()) //Use Any method to improve performance
{
switch (statusID)
{
case (int)GenericEnum.EventStatus.TodaysEvents:
var todaysEvents = planEvents.Where(o => o.EventDate.Date == DateTime.Today.Date);
var todaysTotalEvents = todaysEvents.Count();
var currentHour = DateTime.Now.Hour;
var pastEvents = todaysEvents.Where(e=> e.EventDate.Hour < currentHour);
var presentEvents = todaysEvents.Where(e=> e.EventDate.Hour == currentHour);
var futureEvents = todaysEvents.Where(e=> e.EventDate.Hour > currentHour);
break;
}
}

How do i check if a set time equals the system Time

I'm making a little alarm clock as a project to practice as I'm just a beginner.
I got 2 textboxes in which the user can put in the hours and minutes at which he wants the alarm to go off.
How do i check if the alarm time provided by the user is the same as the time on his system / pc?
Use
int hours = System.DateTime.Now.Hour;
int minutes = System.DateTime.Now.Minute;
if(Convert.Toint32(txtHours.Text) == hours && Convert.Toint32(txtMinutes.Text) == minutes)
{
// same time
}
else
{
// time not same
}
Here is a litle sample to get you on your way
int myMinute = 5;
int myHour = 19;
if (DateTime.Now.Minute == myMinute && DateTime.Now.Hour == myHour)
{
}
All above answers are helpful but you should make in practice to use TimeSpan for comparing date or time.
int hour=5;
int min=20;
int sec=0;
TimeSpan time = new TimeSpan(hour, min, sec);
TimeSpan now = DateTime.Now.TimeOfDay;
// see if start comes before end
if (time == now)
{
//put your condition
}
Please see this url for more info.
How to check if DateTime.Now is between two given DateTimes for time part only?
var current = DateTime.Now;
if (current.Hour == 9 && current.Minute == 0) {
//It is 9:00 now
}
if(Convert.ToInt32(tbHours.Text) == DateTime.Now.Hours
&& Convert.ToInt32(tbMinutes.Text) == DateTime.Now.Minutes)
{
//set off alarm
}

Recursion Help required with C#

On our windows application, We have startDate and EndDate. On click of Execute button event, we need to call a third party web service with our search string + daterange( date from 01/01/2010 to 12/31/2010). Now our search criteria can return us thousands of records but web service have limitation of able to return only 10K records per transaction.
Which required us to break down our dateRange. So basically we need following;
For (X dateRange if RecordCount > 10000) then
X dateRange/2 which will be 01/01/2010 to 06/01/2010 in our case and check condition again and do this recursively until we get daterange block where RecordCount is < 10000.
Then start with Next date, for example, if we get 9999 records for 01/01/2010 to 03/30/2010 then we need to get records for next block starting 04/01/2010
Is this possible with Recursion?
RecursionFunction(dtStart, dtEnd)
{
if (WebService.RecordCount > 9999)
{
TimeSpan timeSpan = dtEnd.Subtract(dtStart);
DateTime mStart = dtStart;
DateTime mEnd = dtStart.AddDays(timeSpan.Days / 2);
RecursionFunction(dtStart,dtEnd);
}
else
{
Get Records here
}
}
But with above code, recursion will have following blocks
01/01/2010, 12/31/2010 > 10000
01/01/2010, 07/03/2010 > 10000
01/01/2010, 04/02/2010 < 10000
So after finishing getting record, recursion will start again with block 01/01/2010,07/03/2010 which we don't need. We need to start next recursion with 04/03/2010,12/31/2010
Thanks in advance for help.
It looks like you are trying to split the input range until it is small enough to handle. Try calling it for both ranges:
RecursionFunction(mStart, mEnd);
RecursionFunction(mEnd.AddDays(1), dtEnd);
The first step is to change the RecursionFunction call (at line 8 of your example) to:
RecursionFunction(mStart, mEnd);
But, then, you'll also need to call it again with the other half of the date range.
RecursionFunction(mEnd + AddDays(1), dtEnd);
Also, you need to handle the results (presumably combining the two answers).
var set1 = RecurseFunction(...);
var set2 = RecurseFunction(...);
return set1.Concat(set2);
This is like divide and conquer. You need to get results from the left and the right of the split and combine them and return that value. So you can keep getting smaller until you have enough data you can deal with and just return that. Then keep joining the result sets together.
public IList<Data> GetRecords(DateTime start, DateTime end)
{
var RecordCount = WebService.RecordCount(start, end);
if (RecordCount < 10000) return WebService.GetRecords(start, end);
DateTime l, m, e;
l = start;
e = end;
var midDay = end.Subtract(start).TotalDays / 2;
m = start.AddDays(midDay);
var left = GetRecords(l, m);
var right = GetRecords(m.AddDays(1), e);
return left.Concat(right);
}
This is how I would do it
static List<string> RecursiveGet(DateTime StartDate, DateTime EndDate, List<string> Output)
{
if (Webservice.RecordCount > 9999)
{
TimeSpan T = EndDate.Subtract(StartDate);
T = new TimeSpan((long)(T.Ticks / 2));
DateTime MidDate = StartDate.Add(T);
Output.AddRange(RecursiveGet(StartDate, MidDate, Output));
Output.AddRange(RecursiveGet(MidDate.AddMilliseconds(1), EndDate, Output));
}
else
{
//Get Records here, return them in array
Output.Add("Test");
}
return Output;
}
static List<string> GetRecords(DateTime StartDate, DateTime EndDate)
{
return RecursiveGet (StartDate, EndDate, new List<string>());
}
Note, Couldn't test it
It works by dividing the dates in half, then searching each of them, and if one is still bigger than 9999, then doing it again.
An easy way would be a form of pagination. If your using JSON or XML, you can put the amount of total results and just return a set number of results (return the offset too). This way you can do a loop to check if your on the last page and after you get the last results page, break out of it.
Don't forget to put checks in if a particular transaction fails though. It's not an ideal solution on such a large dataset but it is a workaround
It sounds much easier to just reuse the last date for the data you actually got back in a while-loop than to home in with recursion like this.
Then start with Next date, for example, if we get 9999 records for 01/01/2010 to 03/30/2010 then we need to get records for next block starting 04/01/2010
March has 31 days.
Pseudo-C# code
var dtStart = DateTime.Parse("2010-01-01");
var dtEnd = DateTime.Parse("2010-12-31");
var totalRecords = new List<RecordType>();
var records = WebService.Get(dtStart, dtEnd);
totalRecords.Add(records);
while (dtStart < dtEnd && records.Count > 9999)
{
dtStart=records.Last().Date;
records = WebService.Get(dtStart, dtEnd);
totalRecords.Add(records);
}
To ease the load on the service you could calculate the timespan for the previous run and only get that many days for the next run in the while-loop.
How you should handle the inevitable doublets depends on the data on the records.
I just realized I presumed you had a date in the returned data. If not, then disregard this answer.

please help optimize this loop

i need to calculate the number of workdays between two dates. a workday is any day between Monday through Friday except for holidays. the code below does this, but it uses a loop. does anyone see a way to get rid of the loop or at least optimize it?
thanks
konstantin
using System;
using System.Linq;
namespace consapp
{
static class Program
{
static void Main(string[] args)
{
var holidays = new DateTime[] { new DateTime(2010, 11, 23), new DateTime(2010, 11, 30) };
var date_start = new DateTime(2010, 12, 3);
var date_end = date_start.AddDays(-9.9);
var duration = (date_end - date_start).Duration();
for (var d = date_end; d < date_start; d = d.Date.AddDays(1))
{
if (holidays.Contains(d.Date) || d.DayOfWeek == DayOfWeek.Saturday || d.DayOfWeek == DayOfWeek.Sunday)
{
duration -= TimeSpan.FromDays(1) - d.TimeOfDay;
}
}
Console.WriteLine(duration);
}
}
}
I would investigate an algorithm like the following. (Sorry no code provided.)
Count the number of full 7-day weeks between your start and end date. You should be able to do this with .NET DateTime and TimeSpan objects.
For each full 7-day week, add 5 days to your result.
Figure out the partial weeks including your start and end dates.
Loop through your holidays and reduce your result by 1 for each holiday between your start and end date. Looping is better here because there are likely far fewer holidays to loop over than days between your start and end date.
Have fun!
EDIT: For source code, check out this answer: Calculate the number of business days between two dates?
Is performance really problematic here? Unless profiling suggests otherwise I'd guess this code doesn't really slow down your application. It's performance should be fine unless you calculate the workdays for thousands of long intervals per second.
If your holiday list is much larger than just two dates then convert it into a HashSet<T> which has O(1) lookup time.
And of course you can turn around the code. So you don't loop over the days in the interval, but over the holidays. Then you just calculate the number of week-days in the interval(should be simple math) and subtract the number of holidays that fall on a week-day.
If it's really necessary you can pre-calculate the workdays since some fixed date, and then subtract the lookup result from the beginning of the period from the lookup result from the end of the period.
if you want faster code, don't loop over each day in the range:
remove from your list of holidays all holidays that fall on sunday or saturday, then use the timespan methods to give you the number of days between the two dates. With a little math (think about integer division by 7) you can get the number of mon-thursday days in that range, subtract the number of holidays that don't fall on the weekend from that number and you are done.
Just roll with it as is. This is not going to waste much time since the bounds are small. When you have some working code, move on. No need to mercilessly optimise code for no reason.
just because I started this as a fun puzzle, here's the code:
[Test]
public void TestDateTime() {
var start = DateTime.Now.Date;
var end = DateTime.Now.Date.AddDays(35);
var workdays = (end - start).Days - ((end - start).Days/7)*2
- (((end - start).Days%7==0)?0:(((int)start.DayOfWeek==0)?1:Math.Max(Math.Min((int)start.DayOfWeek + (end - start).Days%7 - 6, 2), 0)));
new []{DateTime.Now.AddDays(19), DateTime.Now.AddDays(20)}.ToList().ForEach(
x => { if (x.DayOfWeek != DayOfWeek.Saturday && x.DayOfWeek != DayOfWeek.Sunday) workdays--; });
Console.Out.WriteLine("workdays = {0}", workdays);
}
Christmas day and Boxing day are included as holidays.

DateTime interval restriction in C#

The problem:
I am in process of implementing a scheduler for my advisor in school. The scheduler supposes to setup a 15 minutes interval time slot from 8:00 AM to 5:00 PM, Monday to Friday. In addition, the advisor will have to specify the start and end dates of the scheduler. The scheduler will also feature an option to specify if the 15 minutes time slot is not open. Meaning my advisor will be able to mark specific time slot as NOT AVAILABLE.
What I have so far:
I have created a simple class:
public class TimeSlot
{
public DateTime dateTime
{
get;
set;
}
public bool isAvailable
{
get;
set;
}
TimeSlot(DateTime dt, bool Avalible)
{
dateTime = dt;
isAvailable = Avalible;
}
}
The class basically represents an object for one time slot in the scheduler. I also have a list of time slots that keeps a list of the valid time slots:
List<TimeSlot> TSList = new List<TimeSlot>();
Note that a valid time slot means the following:
Date is within: Monday to Friday.
Time is within: 8:00 AM to 5:00 PM
Time slots are within: 15 minutes interval.
In addition, I have a method that fill in the TSList as the following:
private void button_Next_Click(object sender, RoutedEventArgs e)
{
/* Getting the values of fromDate and toDate from the GUI controls*/
DateTime fromDate = datePicker1.SelectedDate.Value;
DateTime toDate = datePicker2.SelectedDate.Value;
while (fromDate <= toDate)
{
/*This ensures that we only deal with days Monday to Friday*/
if (fromDate.DayOfWeek.ToString() != "Saturday" && fromDate.DayOfWeek.ToString() != "Sunday")
{
/*PROBLEM HERE!!*/
}
/*Updating fromDate: Incrementing fromDate by 1 day*/
fromDate = fromDate.AddDays(1);
}
}
Notes that I was only able to satisfy the first condition in my valid time slot conditions. Thus, I was only able to restrict the dates to be within Monday to Friday range.
The questions:
I am trying to achieve the missing two valid conditions for a time slot:
How to restrict the times to be only 8:00am to 5:00 pm?
How to make time slots separated by 15 minutes interval?
First, please use DayOfWeek.Saturday and DayOfWeek.Sunday for the comparision, converting to a string is not necessary...
Then just use a simple loop like
DateTime startSlot = fromDate.Date.AddHours(8); // Starts at 8:00AM
while (startSlot.Hour < 17) {
// Construct time slot class
startSlot = startSlot.AddMinutes(15);
}
This gives you startSlot values starting at 8:00am at every date ranging to 5pm (i.e. the last one is 4:45pm).
Why are you considering building this out of nothing?
Why are you not starting with one of the many calendar management programs that are available off the shelf? For example, Microsoft Outlook contains calendar and schedule management, and you can do all of what you describe, easily. It also integrates with other scheduling tools via .ICS files, it syncs with mobile devices, syncs with Google Calendar, and so on.
But there are lots of other options. Google Calendar is another obvious one.
I don't know why you would ever consider starting from scratch. Unless it's an academic exercise (and no, I don't mean that you work in academia), then you should use larger building blocks to start.
It's like building a structure, starting with sand and water, instead of pre-fabricated concrete block.
Just quick implementation. Let me know if you need some comments.
// Round interval
const int roundInterval = 15;
var remainder = fromDate.TimeOfDay.Minutes % roundInterval;
var curTime = remainder == 0 ? fromDate : fromDate.AddMinutes(roundInterval - remainder);
curTime = curTime.AddSeconds(-curTime.TimeOfDay.Seconds);
var delta = TimeSpan.FromMinutes(roundInterval);
while (curTime < toDate)
{
while (curTime.DayOfWeek == DayOfWeek.Saturday || curTime.DayOfWeek == DayOfWeek.Sunday)
{
curTime = curTime.Date.AddDays(1);
}
if (curTime.TimeOfDay.Hours < 8)
{
curTime = curTime.AddHours(8 - curTime.TimeOfDay.Hours);
curTime = curTime.AddMinutes(-curTime.TimeOfDay.Minutes);
continue;
}
if (curTime.TimeOfDay.Hours >= 17)
{
curTime = curTime.AddHours(24 - curTime.TimeOfDay.Hours);
curTime = curTime.AddMinutes(-curTime.TimeOfDay.Minutes);
continue;
}
TSList.Add(new TimeSlot(curTime, true));
curTime = curTime.Add(delta);
}
}
DateTime myScheduledTimeSlot = new DateTime(2010, 10, 26, 8, 45, 0);
// Use existing check to check day of week constraint...
// Check if the datetime falls on a correct minute boundary
switch (myScheduledTimeSlot.Minute)
{
case 0:
case 15:
case 30:
case 45:
// The time slot is valid
break;
default:
// The time slot is not valid
break;
}
It is pretty simple to check whether it falls in a 15 minute slot as you don't have weird boundaries keeping every hour identical. I'd recommend checking out Quart.NET if you want to save some time doing eventing/scheduling.

Categories

Resources