Find consecutive 12 month rolling periods based on a condition - c#

I'm trying to build a calculator to identify the earliest finish date with 5 consecutive 12 month rolling periods which satisfy a specific condition (absence less than 180 days in my example)
The code starts with a fixed start date and adds 12 months to calculate the absence period in any given window. If the absence period is greater than 180 days, it should adjust the start date so the absence is less than 180 days and continue till 5 such consecutive periods are found
I can think of the brute force solution but would love to know any more elegant solutions.
public void CalculateAbsence()
{
var startDate = new LocalDate(2018, 5, 5);
var qualifyinYears = 0;
while (qualifyinYears < 5)
{
var totalAbsence = 0;
var endDate = startDate.PlusYears(1);
//Retrieve All applicable absences in this qualifying Period
foreach (var abs in Immigration.ApplicableAbsences(startDate, endDate))
{
totalAbsence += Period.DaysBetween((abs.Start < startDate ? startDate : abs.Start), (abs.End > endDate ? endDate : abs.End));
}
Console.WriteLine($"Year {startDate}-{endDate}. Absence: {totalAbsence}");
qualifyinYears++;
startDate = startDate.PlusYears(1);
}
}

Related

Subtract DateTime in C# exluding weekends AND holidays [duplicate]

This question already has answers here:
C# How to calculate working days excluding specific dates (Holidays)
(4 answers)
Closed 1 year ago.
The community reviewed whether to reopen this question 1 year ago and left it closed:
Original close reason(s) were not resolved
I'm creating an API and I need to subtract a certain number of periods and make sure I only quantify business days (excluding weekends and holidays) but I'm having trouble.
I've found some useful solutions to only capture weekdays when I subtract from dateTime.Now() but I need to exclude US federal holidays as well.
I'd probably just scroll it with a loop, repeatedly adding or subbing a period and testing upon each add/sub if the current day is banned, sub a whole day:
DateTime ScrollSkipping(DateTime start, TimeSpan period, int numPeriods, HashSet<DateTime> hashsetOfPublicHolidays){
var d = start; //eg new DateTime(2021, 12, 26, 0, 30, 0);
var t = period; //eg -1 hour to go backwards
var skip = TimeSpan.FromDays(period<TimeSpan.Zero?-1:1);
var p = numPeriods; // eg 25 times
for(int x = 0; x < p;){
if(d.DayOfWeek is DayOfWeek.Saturday or DayOfWeek.Sunday || hashsetOfPublicHolidays.Contains(d.Date))
d += skip;
else{
d += t;
x++;
}
}
}
If you supplied a TimeSpan.FromHours(-1); as the period and 25 as the number of periods, and don't "use up" a period when you're skipping whole days for some reason, then resume decrementing it when you're back on a normal date then you'll skip completely over the weekends/holidays.
To go backwards supply a negative TimeSpan as the period, forwards positive
Obviously you need to know the 'US Federal holidays' There are some paid APIS that provide those data or as US holidays ar very simple, use a list built from this: https://www.law.cornell.edu/uscode/text/5/6103

What condition should we write to get gaps between dates at least 28 days?

I am writing a code in which I have taken start date and end date as input.(and want to show date between these range) Now I want to make sure that the gap between these two dates should be greater than 28 days i.e. 4 week. If user giving two dates having gap of 5 days then the start date should be change accordingly.
I tried some if else conditions but not getting the desired result.
***
if(enddate == DateTime.Now.Date){ startdate = ed.AddDays(-28);}
else if(enddate < )
else if()
else
***
What should be the other conditions?
Something like:
var startdate = DateTime.Now;
var enddate = DateTime.Now.AddDays(5);
if((enddate-startdate).Days<28)
{
startdate = enddate.AddDays(-28);
}
After if statement the gap between startdate and enddate will be at least 28 days

Comparing dates in C#

I am a beginning programmer in C# and asp.net. I am busy trying to create a Hotel application. Where somebody is able to book for example an 8 day vacation. But now I need to add a formula that calculates the price. The method I am writing is getting the price per night of the room from the database. And the days that the person is staying is entered in the view and passed down to the controller.So I want to calculate the price inside the controller. But now I have a problem cause the price of staying in the hotel is higher in the high-season than in the low-season. So the prices differs per day. But now I do not really now how to compare the dates so I am able to give an accurate total price.
I have looked over some threads on stack overflow and they often advice to use Timespan to compare dates. But I was wondering is Timespan the best solution for me? Cause for my project the price should flow and not be fixed. For example it should not be like 28 May - 10 July is €120 euro per night but more like 28 May €109, 29 May €112, 30 May €113 - 9 July €127, 10 July 130.
If I would succeed in creating a different price per day then the last thing should not be that hard I hope. The price of each date should be added to each other so I will have the total price.
So my questions are:
Is the best way to compare dates Timespan?
Is there an easy way to calculate this? I would not like fixed dates.
Are there any good tutorials for this?
I would just compare each Date object between the start and end dates to see if it falls within a defined range to determine the rate, and sum them as I go.
This is probably overkill for you, but I would encapsulate the different 'seasons' and their rates in a class, and add a method to the class that will determine if a date falls within that 'season'. This will simplify the other methods.
Then I would create a method that, given a single date, will return the rate for that date.
Finally, I would calculate the total price by calling the GetRate() method for each day between the client's start date (inclusive) and end date (exclusive).
Here's a sample of how I would do it. First, the class to hold a 'season'
public class Season
{
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public int Rate { get; set; }
public bool ContainsDate(DateTime date)
{
// Assumption: Year is ignored - seasons are considered
// to start and end on the same date each year
//
// Rules: (remember a season may start in Dec and end in Jan,
// so you cant just check if the date is greater than
// the start or less than the end!)
//
// 1. If the start and end month are the same,
// return true if the month is equal to start (or end) month
// AND the day is between start and end days.
// 2. If the date is in the same month as the start month,
// return true if the day is greater than or equal to start day.
// 3. If the date is in the same month as the end month,
// return true if the day is less than or equal to end day.
// 4. If the StartMonth is less than the EndMonth,
// return true if the month is between them.
// 5. Otherwise, return true if month is NOT between them.
if (StartDate.Month == EndDate.Month)
return date.Month == StartDate.Month &&
date.Day >= StartDate.Day &&
date.Day <= EndDate.Day;
if (date.Month == StartDate.Month)
return date.Day >= StartDate.Day;
if (date.Month == EndDate.Month)
return date.Day <= EndDate.Day;
if (StartDate.Month <= EndDate.Month)
return date.Month > StartDate.Month && date.Month < EndDate.Month;
return date.Month < EndDate.Month || date.Month > StartDate.Month;
}
}
Next, a method that will calculate the rate for a specific date:
public static int GetRate(DateTime date)
{
// Normally these 'seasons' and rates would not be hard coded here
const int offSeasonRate = 125;
var winterSeason = new Season
{
StartDate = DateTime.Parse("November 15"),
EndDate = DateTime.Parse("January 12"),
Rate = 150
};
var springSeason = new Season
{
StartDate = DateTime.Parse("May 20"),
EndDate = DateTime.Parse("June 15"),
Rate = 140
};
var summerSeason = new Season
{
StartDate = DateTime.Parse("July 10"),
EndDate = DateTime.Parse("August 31"),
Rate = 170
};
// Create a list of all the seasons
var seasons = new List<Season> {winterSeason, springSeason, summerSeason};
// Loop through all the seasons and see if this date is in one of them
foreach (var season in seasons)
{
if (season.ContainsDate(date))
{
// Note: depending on your implementation, Rate could be a multiplier
// in which case you would return (offSeasonRate * season.Rate);
return season.Rate;
}
}
// If we get this far, the date was not in a 'season'
return offSeasonRate;
}
Finally, here is the method that gets the total price for a date range:
var startDate = DateTime.Today;
var endDate = startDate.AddDays(2);
var price = 0;
// Sum the rates for each day between
// start date (inclusive) and end date (exclusive).
for (var curDate = startDate; curDate < endDate; curDate = curDate.AddDays(1))
{
price += GetRate(curDate);
}
Console.WriteLine("The total cost from {0} to {1} is: €{2}",
startDate, endDate, price);

linq compare column data between two dates

I need to compare the scores of a user between last week and two weeks ago.
i have a table like so
Scores
user score subject date
2 10 math 21/10/2012
2 5 science 23/10/2012
2 5 math 16/10/2012
2 9 science 15/12/2012
I need to produce a query that shows last week's score and whether it is an increase or decrease from 2 weeks ago's score
user score subject date increase/decrease
2 10 math 21/10/2012 +5
2 10 science 23/10/2012 -4
The date column doesn't need to be included in the query
I already have the code to get week range from last week to two weeks ago. I'm having trouble comparing the two dates however.
DateTime date = DateTime.Now;
DateTime startOneWeekAgo = date.AddDays(-7).Date.AddDays(-(int)date.DayOfWeek),
endOneWeekAgo = startOneWeekAgo.AddDays(7);
DateTime startTwoWeeksAgo = startOneWeekAgo.AddDays(-7),
endTwoWeeksAgo = endOneWeekAgo.AddDays(-7);
from s in Scores where s.scoredate >= startOneWeekAgo && s.scoredate <
endOneWeekAgo
this results in. This is what I have so far. Help would be appreciated.
user score subject
2 10 math
2 5 science
DateTime beginningOfWeek = DateTime.Now.BeginningOfWeek();
DateTime twoWeeksAgo = beginningOfWeek.AddDays(-14);
DateTime endOfLastWeek = beginningOfWeek.AddMilliseconds(-1);
var query = from s in scores
where s.Date >= twoWeeksAgo && s.Date <= endOfLastWeek
orderby s.Date
group s by new { s.User, s.Subject } into g
select new
{
User = g.Key.User,
Subject = g.Key.Subject,
Date = g.Last().Date,
Diff = g.Last().Score - g.First().Score
};
Thus you always selecting only two last scores (two weeks ago and one week ago), you will have only two records in each group.
If you will have only one week's results in database, then difference will be zero, because last and first entry in group will be the same.
Also you can use some DateTime extension for obtaining beginning of week:
public static class DateExtensions
{
public static DateTime BeginningOfWeek(this DateTime date,
DayOfWeek firstDayOfWeek = DayOfWeek.Monday)
{
if (date.DayOfWeek == firstDayOfWeek)
return date.Date;
DateTime result = date.AddDays(-1);
while (result.DayOfWeek != firstDayOfWeek)
result = result.AddDays(-1);
return result.Date;
}
}
And one more thing - try to avoid declaring several variables at once.

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;

Categories

Resources