Disabling weekend and national Holidays in ajax calendar extender control - c#

I have been trying to use an ajax CalenderExtender for my application.
I have many small operations in my app like adding duration to start date of a task to find the finish date, change duration of a task if its end date is changed (depending on its start date),etc.
But while I do all these operations I want to skip all the holidays and saturday , sundays from the calculations for eg. a task starting on 01/23/2014 with a duration of 5 days should finish on 01/29/2014 (adding 2 days for sat n sun in duration) instead of 01/27/2014. Same should be performed on other operations as well.
Is there a way to do this?

For Sundays and Saturdays, it's easy. Just check the DateTime.DayOfWeek property of your dates.
If you have an operation that will start on date start and will end on date end, you can see what dates are Saturdays or Sundays like this:
List<DateTime> satsAndSundays;
for (DateTime temp = start; temp <= end; temp.AddDays(1))
{
if (temp.DayOfWeek == DayOfWeek.Sunday ||
temp.DayOfWeek == DayOfWeek.Saturday)
{
satsAndSundays.add(temp);
}
}
And since you can know how many days there are between start and end by doing something like:
TimeSpan span = end - start;
int totalDays = (int)span.TotalDays;
// TotalDays is actually a double, I'm just discarding the non integer part.
You may fid out how many work days you have there by doing totalDays - satsAndSundays.Count.
Edit: I just read the question again. If you want a task to start on a given date, and take x work days, you can do it like this:
DateTime end = start;
for (int i = x; i >= 0;) // the third parameter of the for is empty on purpose
{
end = end.AddDays(1);
if (end.DayOfWeek != DayOfWeek.Saturday &&
end.DayOfWeek != DayOfWeek.Sunday)
{
i--;
}
}
Afther the loop, end will be x workdays after start (provided there are no holidays in between).
For holidays, though, there is no alghoritm for that in the framework. You need to fetch them from some source (a file, a database, a web service etc.). Or you could write your own program to figure them out - most holidays that are not on a fixed date do follow formulas when it comes to when they happen. Do take into account, however, that holidays may vary by culture and region. If your application is to be used throughout a country, for example, it may be quite the effort to implement city-wide holidays. Depending on your needs, it might even be better to either let the users input which days are holidays, or making your own database your app can access and use.

Try this one..
private string GetDatesOfSundays(DateTime DatMonth)
{
string sReturn = "";
int iDayOffset = DatMonth.Day - 1;
DatMonth = DatMonth.AddDays(System.Convert.ToDouble(-DatMonth.Day + 1));
DateTime DatMonth2 = DatMonth.AddMonths(1).AddDays(System.Convert.ToDouble(-1));
while (DatMonth < DatMonth2)
{
if (DatMonth.DayOfWeek == System.DayOfWeek.Sunday)
{
if (sReturn.Length > 0) sReturn += ",";
sReturn += DatMonth.ToShortDateString();
}
DatMonth = DatMonth.AddDays(1.0);
}
return sReturn;
}

Related

Datetime elapsed

I have this quote:
var deadline=System.DateTime.Now;
deadline = new System.DateTime(deadline.Year, deadline.Month, deadline.Day, deadline.Hour+4, deadline.Minute, 0);
And I would like to transform it with a workday system.
The current input is 2022-02-15 14:25:00.000
The output is: 2022-02-15 18:25:00.000
A regular workday would be weekdays 08:00-16:00
So right now the output is elapsed by 02:25, and I would like to add for the next workday.
New output: 2022-02-16 10:25:00.000
I am not sure what condition should I need and how could I skip weekends too at once.
Thank you in advance,
There are several steps here.
First, although I assume your input is going to logically be inside a working day, I would not just add 4 to the hours. On the off chance that DateTime.Now returns a value that is closer to midnight than those 4 hours, it would throw an exception.
And if you want your solution to be general, as in you would be able to say "the deadline is 30 hours from now, only counting working hours", it wouldn't be able to work at all, even within a working day.
So, with that in mind, here's my proposal, expressed as pseudo-code
left (TimeSpan) = 4 # can be changed to whatever
timestamp = DateTime.Now
while left > 0
if timestamp > end of working day OR not even a working day at all
then:
set timestamp to start of next working day
else:
calculate remainder = how much is left of current working day from "timestamp"
if less than left
then:
add left to timestamp
return timestamp as deadline
else:
subtract remainder from left
set timestamp to start of next working day
Here is C# code that should accomplish this.
Some of the pieces are missing error handling, and can probably be optimized a lot.
void Main()
{
var start = new DateTime(2022, 2, 21, 11, 34, 0);
var deadline = GetDeadline(start, TimeSpan.FromHours(30));
Console.WriteLine($"{start} + 30h in working hours = {deadline}");
}
public static DateTime GetDeadline(DateTime timestamp, TimeSpan timeUntilDeadline)
{
if (timeUntilDeadline <= TimeSpan.Zero)
return timestamp;
(DateTime start, DateTime end) nextWorkingDay;
while (timeUntilDeadline > TimeSpan.Zero)
{
var workingDay = GetWorkingDay(timestamp.Date);
if (!workingDay.HasValue || timestamp >= workingDay.Value.end)
{
nextWorkingDay = GetNextWorkingDay(timestamp.Date);
timestamp = nextWorkingDay.start;
continue;
}
if (timestamp < workingDay.Value.start)
timestamp = workingDay.Value.start;
var remainder = workingDay.Value.end - timestamp;
if (remainder > timeUntilDeadline)
remainder = timeUntilDeadline;
timestamp += remainder;
timeUntilDeadline -= remainder;
}
return timestamp;
}
public static (DateTime start, DateTime end)? GetWorkingDay(DateTime date)
{
// todo: handle holidays and vacations?
switch (date.DayOfWeek)
{
case DayOfWeek.Monday:
case DayOfWeek.Tuesday:
case DayOfWeek.Wednesday:
case DayOfWeek.Thursday:
case DayOfWeek.Friday:
return (date + TimeSpan.FromHours(8), date + TimeSpan.FromHours(16));
default:
return null;
}
}
public static (DateTime start, DateTime end) GetNextWorkingDay(DateTime date)
{
while (true)
{
date = date.AddDays(1);
var workingDay = GetWorkingDay(date);
if (workingDay.HasValue)
return workingDay.Value;
}
}
Output:
21.02.2022 11:34:00 + 30h in working hours = 25.02.2022 09:34:00
The output is due to:
The start timestamp is Tuesday, 11:34
30 hours, only counting working days would first fill out Tuesday, consuming 4:26, giving us 25:34 left to process
Wednesday, Thursday, Friday, all consume 8 hours each, reducing the processing value down to 1:34
On Monday 25th, the deadline is thus 09:34
Corner-cases considered in the code:
If your starting-time is on a day without working hours (Saturday, Sunday), the next working day start is used instead
If your starting-time is after the end of a working-day (18:00 on a Monday for instance), the start of the next working day is again used
If your starting-time is before the start of a working-day (06:00 on a Monday for instance), the start of that working day is used
You can easily enhance the "get the working hours for this date" method to handle such things as holidays, vacations, or even non-typical days with, say, only 4 hours work, or late shifts, or whatever.

Algorithm listing all possible timespans within a timespan

I'm struggeling a bit with an algorithm implementation.
I am having a start date and an end date and I want to list all possible timespans within that timespan with a special condition as start and end dates.
For example:
My start date is 01-01-2020 and my end date is 31-01-2020. My condition is to list all possible timespans that have at least 7 days and maximum 10 days.
So the result set would be like:
01-01-2020 -> 08-01-2020
01-01-2020 -> 09-01-2020
...
02-01-2020 -> 09-01-2020
...
24-01-2020 -> 31-01-2020
Preferable as Linq so I can enumerate.
Here's a simple implementation. It's not the most efficient, but it's easy to understand:
public static IEnumerable<(DateTime start, DateTime end)> ListTimespans(DateTime startDate, DateTime endDate, int minDays, int maxDays)
{
// Loop through all of the possible starts. The first day we can start on is startDate,
// and the last day we can start on is endDate - minDays (which gives us a span
// minDays long ending on endDate)
for (var start = startDate; start <= endDate.AddDays(-minDays); start = start.AddDays(1))
{
// For each of these starts, loop through the possible end dates. There are two
// limits to the end date: either hit the maximum number of days for a span
// (start.AddDays(maxDays)), or we hit the end date.
// Loop until whichever one comes first.
for (var end = start.AddDays(minDays); end <= Min(start.AddDays(maxDays), endDate); end = end.AddDays(1))
{
yield return (start, end);
}
}
DateTime Min(DateTime x, DateTime y) => x < y ? x : y;
}
See it in action here.

how to get no of days and nights between two dates using c#

i am doing a project on cab services.in this rate is different for day and night.
in the form only journey start date and end date is selected.based on this i have to calculate the no of days and nights.
here i am confused how to calculate the no of days and night.
thanks in advance.
private List<DateTime> GetDateRange(DateTime StartingDate, DateTime EndingDate)
{
if (StartingDate > EndingDate)
{
return null;
}
List<DateTime> rv = new List<DateTime>();
DateTime tmpDate = StartingDate;
do
{
rv.Add(tmpDate);
tmpDate = tmpDate.AddDays(1);
} while (tmpDate <= EndingDate);
return rv;
}
To view this code in action, copy and paste the following code into SnippetCompiler:
DateTime StartingDate = DateTime.Parse("02/25/2007");
DateTime EndingDate = DateTime.Parse("03/06/2007");
foreach (DateTime date in GetDateRange(StartingDate,EndingDate))
{
WL(date.ToShortDateString());
}
Sample output :
2/25/2007
2/26/2007
2/27/2007
2/28/2007
3/1/2007
3/2/2007
3/3/2007
3/4/2007
3/5/2007
3/6/2007
Use the Subtract method to get the difference, which is a TimeSpan value. Example:
TimeSpan diff = SecondDate.Subtract(FirstDate);
You can get the length of the time span for example in hours:
double hours = diff.TotalHours;
I'm not sure which time unit "days and nights" could be interpreted as, though. Perhaps days?
double days = diff.TotalDays;
DateTime dt1,dt2;
//...
TimeSpan period = dt1 - dt2;
int days = period.Days;
It sounds like a very long Cab journey that takes days and nights!
I think you need to define what a day and a night is more clearly in order to get your perfect answer. You also need to think about what impact Daylight Saving Time has on your calculations.
If say:
a day was the period from 6am to 6pm
the night was the rest - from 6pm to 6am
and you wanted to really count hours rather than days
In this case then a calculation would require you to:
iterate a currentDateTime from the startDateTime to the endDateTime
choose the increment in the currentDateTime so that it jumps to the next time barrier (6am, 6pm or the endDateTime)
within each loop, then add to your cumulative calculation of numDayHours or numNightHours so far.
Note that:
you could make this calculation quicker by counting whole days along the way
you need to be very careful about the time zone you are calculating in (I just hope that your taxi doesn't cross time zone boundaries!)
you need to be very careful about local time changes - especially "daylight savings time" type changes - the duration from 6pm to 6am is not always 12 hours!
Some pseudo code:
var numDayHours = 0.0;
var numNightHours = 0.0;
var current = startDateTime;
while (current < endDateTime)
{
next_hop = calculate_next_hop (current, endDateTime);
// select next date time
switch (next_hop.hop_type)
{
case HopType.night_time_hop:
numNightHours += next_hop.num_hours;
break;
case HopType.day_time_hop:
numDayHours += next_hop.num_hours;
break;
}
current = next_hop.EndDateTime;
}
// and here is the result
double numDays = numDayHours / 12.0;
double numHours = numNightHours / 12.0;

C# DateTime falls within the last 24 hours

I have a DateTime object that I'd like to check and see if it falls within the last 24 hours.
I did something like this but its wrong:
myDateTime > DateTime.Now.AddHours(-24) && myDateTime < DateTime.Now
where did I go wrong?
There is nothing wrong with the code that you posted, so whatever you did wrong is somewhere else in the code.
I only see two minor flaws in the code, but they only affect corner cases:
You should avoid getting the DateTime.Now property repeatedly in the code. Its value changes, so you may get inconsistent results in some cases when the values changes from one use to the next.
To get a time interval you would usually pair one inclusive and one exclusive operator, like > and <=, or >= and <. That way you can check for intervals next to each other, like 0 - 24 hours and 24 - 28 hours, without getting a gap or an overlap.
DateTime now = DateTime.Now;
if (myDateTime > now.AddHours(-24) && myDateTime <= now)
Only get DateTime.Now once within the function - otherwise the value might change.
Use <=, not <. if you check a microsecond after the time has been set, it will still be equal to DateTime.Now. I actually ran into this in production code where imports wouldn't show up in a different query that checked < because the import was too fast!
Use this code:
DateTime now = DateTime.Now;
DateTime yesterday = now.AddDays(-1);
if (myDateTime > yesterday && myDateTime <= now) {
...
}
Learning from both the above answers and also to improve the readability of the code we can use a method like this.
using System;
public class Program
{
public static void Main()
{
DateTime myDateTime = DateTime.Parse("2021-08-25T20:20:19.5540211");
DateTime now = DateTime.Now;
DateTime yesterday = now.AddHours(-24);
if (IsBewteenTwoDates(myDateTime, yesterday, now))
{
Console.WriteLine("this date ({0}) is between {1} & {2}", myDateTime, yesterday, now);
}
else
{
Console.WriteLine("this date ({0}) is not between {1} & {2}", myDateTime, yesterday, now);
}
}
// Checks if the DateTime object dt is between start and end DateTime.
public static bool IsBewteenTwoDates(DateTime dt, DateTime start, DateTime end)
{
return dt >= start && dt <= end;
}
}
Check the fiddle here.

How to loop between two dates

I have a calendar which passes selected dates as strings into a method. Inside this method, I want to generate a list of all the dates starting from the selected start date and ending with the selected end date, obviously including all of the dates inbetween, regardless of how many days are inbetween the selected start and end dates.
Below I have the beginning of the method which takes the date strings and converts them into DateTime variables so that I can make use of the DateTime calculation functions. However, I cannot seem to work out how to calculate all of the dates inbetween the start and end date?
Obviously the first stage is to subtract the start date from the end date, but I cannot calculate the rest of the steps.
Help appreciated greatly,
kind regards.
public void DTCalculations()
{
List<string> calculatedDates = new List<string>();
string startDate = "2009-07-27";
string endDate = "2009-07-29";
//Convert to DateTime variables
DateTime start = DateTime.Parse(startDate);
DateTime end = DateTime.Parse(endDate);
//Calculate difference between start and end date.
TimeSpan difference = end.Subtract(start);
//Generate list of dates beginning at start date and ending at end date.
//ToDo:
}
static IEnumerable<DateTime> AllDatesBetween(DateTime start, DateTime end)
{
for(var day = start.Date; day <= end; day = day.AddDays(1))
yield return day;
}
Edit: Added code to solve your particular example and to demonstrate usage:
var calculatedDates =
new List<string>
(
AllDatesBetween
(
DateTime.Parse("2009-07-27"),
DateTime.Parse("2009-07-29")
).Select(d => d.ToString("yyyy-MM-dd"))
);
You just need to iterate from start to end, you can do this in a for loop
DateTime start = DateTime.Parse(startDate);
DateTime end = DateTime.Parse(endDate);
for(DateTime counter = start; counter <= end; counter = counter.AddDays(1))
{
calculatedDates.Add(counter);
}
The easiest thing to do would be take the start date, and add 1 day to it (using AddDays) until you reach the end date. Something like this:
DateTime calcDate = start.Date;
while (calcDate <= end)
{
calcDate = calcDate.AddDays(1);
calculatedDates.Add(calcDate.ToString());
}
Obviously, you would adjust the while conditional and the position of the AddDays call depending on if you wanted to include the start and end dates in the collection or not.
[Edit: By the way, you should consider using TryParse() instead of Parse() in case the passed in strings don't convert to dates nicely]
for( DateTime i = start; i <= end; i = i.AddDays( 1 ) )
{
Console.WriteLine(i.ToShortDateString());
}
An alternative method
public static class MyExtensions
{
public static IEnumerable EachDay(this DateTime start, DateTime end)
{
// Remove time info from start date (we only care about day).
DateTime currentDay = new DateTime(start.Year, start.Month, start.Day);
while (currentDay <= end)
{
yield return currentDay;
currentDay = currentDay.AddDays(1);
}
}
}
Now in the calling code you can do the following:
DateTime start = DateTime.Now;
DateTime end = start.AddDays(20);
foreach (var day in start.EachDay(end))
{
...
}
Another advantage to this approach is that it makes it trivial to add EachWeek, EachMonth etc. These will then all be accessible on DateTime.

Categories

Resources