I am trying to keep track of how many meals a person has given from two dates you can enter from DateTimePickers.
There are three meals a day between specific times between:
6-8AM Meal 1
12-2PM Meal 2
5-7PM Meal 3
If a person arrives after one of the specific times, they miss out on a meal, so for example if I arrive on 1 Jan 2018 3AM and leave on 2 Jan 2018 2PM I will only receive 5 meals, as I missed out on the last meal.
This is the code I have come up with, but unfortunately I struggle to work the code out if the time between the two dates are more than one day apart.
private void button1_Click(object sender, EventArgs e)
{
dateTimeExit.CustomFormat = "MM/dd/yyyy hh:mm:ss tt";
dateTimeArrive.CustomFormat = "MM/dd/yyyy hh:mm:ss tt";
DateTime timeArrived = dateTimeArrive.Value;
DateTime timeExit = dateTimeExit.Value;
int totalHoursArrived = timeArrived.Hour;
int totalHoursExit = timeExit.Hour;
int totalCounts = 0;
int countA = 0; //6-8 AM
int countB = 0; //12-2PM
int countC = 0; //5-7PM
int totalDaysLeft = (timeExit - timeArrived).Days; //determines the number of days between the two given dates.
if (totalDaysLeft == 1)
{
totalCounts = 3;
countA = 1;
countB = 1;
countC = 1;
}
else if (totalDaysLeft < 1) //difference between the two dates is less than a day.
{
totalCounts = totalDaysLeft * 3;
countA = totalDaysLeft;
countB = totalDaysLeft;
countC = totalDaysLeft;
if (timeExit.Day == timeArrived.Day) //if the dates are on the same day and "less than one day"
{
if (totalHoursArrived <= 8 && totalHoursExit >= 17) //if date is before or on 8AM and leaves on or after 5PM.
{
countA = 1;
countB = 1;
countC = 1;
}
else if (totalHoursArrived <= 8 && (totalHoursExit >= 12 && totalHoursExit < 17)) //if date is before or on 8AM and leaves before 5PM
{
countA = 1;
countB = 1;
}
else if (totalHoursArrived <= 8 && totalHoursExit < 12) //if date is before or on 8AM and leaves before 12PM
{
countA = 1;
}
else if ((totalHoursArrived <= 12 && totalHoursArrived > 8) && totalHoursExit >= 17) //if date is before or on 12PM and leaves on or after 5PM
{
countB = 1;
countC = 1;
}
else if ((totalHoursArrived <= 12 && totalHoursArrived > 8) && totalHoursExit < 17) //if date is before or on 12PM and leaves before 5PM
{
countB = 1;
}
else if (totalHoursArrived >= 17) //if date is after or on 5PM
{
countC = 1;
}
totalCounts = countA + countB + countC;
}
else //less than a day, but not on same day exit time.
{
if (totalHoursArrived <= 8) //if date is before or on 8AM.
{
totalCounts = 3;
countA = 1;
countB = 1;
countC = 1;
}
else if (totalHoursArrived >= 12 && totalHoursArrived < 17)// //if date is after or on 12PM and arrival time is less than 5PM
{
totalCounts = 2;
countB = 1;
countC = 1;
}
else if (totalHoursArrived >= 17) //if date is after or on 5PM
{
totalCounts = 1;
countC = 1;
}
if (totalHoursExit > 0) // exit time
{
if (totalHoursExit >= 17)
{
totalCounts += 3;
countA += 1;
countB += 1;
countC += 1;
}
else if (totalHoursExit >= 12 && totalHoursExit < 17)
{
totalCounts += 2;
countA += 1;
countB += 1;
}
else if (totalHoursExit >= 6 && totalHoursExit < 12)
{
totalCounts += 1;
countA += 1;
}
}
}
}
else //more than two days difference between the two dates.
{
**//the part I am struggling to figure out**
}
lblTotalCountA.Text = "Count A: " + countA;
lblTotalCountB.Text = "Count B: " + countB;
lblTotalCountC.Text = "Count C: " + countC;
lblTotalAmount.Text = "Total Counts: " + totalCounts;
}
I find your code quite difficult to mantain (if you would like to add a fourth meal in the future, it would be a nightmare to change your code), so I'm giving you a different approach, as well as answering your question.
First I would define a class like this:
public class DayMeals
{
private int[] entryTimes = new int[] { 6, 12, 17 };
private int[] exitTimes = new int[] { 8, 14, 19 };
private int[] mealCounts = new int[3];
private bool countHalfMeals = false;
public DayMeals(bool countHalfMeals)
{
this.countHalfMeals = countHalfMeals;
}
public void AddFullDay()
{
mealCounts[0]++;
mealCounts[1]++;
mealCounts[2]++;
}
public void CountMealsForADay(DateTime timeArrived, DateTime timeExit)
{
for (int i = 0; i < mealCounts.Length; i++)
{
int mealEntryTime = entryTimes[i];
int mealExitTime = exitTimes[i];
if (timeArrived.Hour <= mealEntryTime && timeExit.Hour >= mealExitTime)
mealCounts[i]++;
else if (countHalfMeals && timeExit.Hour > mealEntryTime && timeExit.Hour <= mealExitTime)
mealCounts[i]++;
}
}
public void PrintMealsCount()
{
for (int i = 0; i < mealCounts.Length; i++)
{
System.Console.WriteLine($"Meal #{i + 1} count = {mealCounts[i]}");
}
}
}
Then, I would simply instantiate the class and call the functions:
void Main(string[] args)
{
CalculateMeals(new DateTime(2019, 1, 1, 15, 12, 1), new DateTime(2019, 1, 2, 18, 0, 0));
}
public static void CalculateMeals(DateTime timeArrived, DateTime timeExit)
{
// Number of full days
int fullDaysNumber = (timeExit - timeArrived).Days;
DayMeals dayMeals = new DayMeals(true);
for (int i = 0; i <= fullDaysNumber; i++)
{
int hoursDiff = (int)(timeExit - timeArrived).TotalHours;
if (timeExit.Day > timeArrived.Day && hoursDiff > 24)
{
dayMeals.AddFullDay();
// A trick to make the cycle work the next time
// You can use a different variable if you want to keep timeArrived unchanged
timeArrived = timeArrived.AddDays(1);
}
else if (timeExit.Day < timeArrived.Day)
{
break;
}
else
{
if (timeArrived.Day != timeExit.Day)
{
dayMeals.CountMealsForADay(timeArrived, new DateTime(1,1,timeArrived.Day,23,59,59));
dayMeals.CountMealsForADay(new DateTime(1,1,timeExit.Day,0,0,1), timeExit);
}
else
{
dayMeals.CountMealsForADay(timeArrived, timeExit);
}
}
}
dayMeals.PrintMealsCount();
}
I tried this code and it seems to work as expected. Please review it and let me know if this is what you wanted to achieve.
NOTE: I know the usage of "AddDays(1)" is counterintuitive, because I am keeping the same hour of day 1 for a subsequent day. But, if you are not interested about the fact that a person entered at 11 on Monday rather than on Tuesday, the meals count is the same. Basically, I'm just traslating the entry time to the last day.
Here you go, without looping. I simplified further by only using standard c# objects. The trick is in counting full days and work with timespans.
public static void Main(string[] args)
{
DateTime timeArrived = new DateTime(2019, 1, 5, 13, 53, 0);
DateTime timeExit = new DateTime(2019, 1, 6, 8, 46, 0);
TimeSpan startMeal1 = new TimeSpan(6, 0, 0);
TimeSpan endMeal1 = new TimeSpan(8, 0, 0);
TimeSpan startMeal2 = new TimeSpan(12, 0, 0);
TimeSpan endMeal2 = new TimeSpan(14, 0, 0);
TimeSpan startMeal3 = new TimeSpan(17, 0, 0);
TimeSpan endMeal3 = new TimeSpan(19, 0, 0);
int daysDiff = (timeExit - timeArrived).Days;
int meals1Count = daysDiff;
int meals2Count = daysDiff;
int meals3Count = daysDiff;
TimeSpan timeDiff = timeExit - timeArrived - TimeSpan.FromDays(daysDiff);
if (timeArrived.TimeOfDay <= endMeal1 && (timeArrived.TimeOfDay + timeDiff) >= startMeal1) meals1Count++;
if (timeArrived.TimeOfDay <= endMeal2 && (timeArrived.TimeOfDay + timeDiff) >= startMeal2) meals2Count++;
if (timeArrived.TimeOfDay <= endMeal3 && (timeArrived.TimeOfDay + timeDiff) >= startMeal3) meals3Count++;
}
I havent checked this in VS but something like this should work. I copied your same day code, assuming its correct also:
public class MealCalculation
{
int countA, countB, countC = 0;
int total = 0;
public void Calculate()
{
var start = DateTime.Now;
var finish = DateTime.Now;
// Same Day
if (start.Date == finish.Date)
{
MealsCalculate(start.Hour, start.Hour);
}
// Next Day
else if (start.AddDays(1).Date == finish.Date)
{
MealsCalculate(start.Hour, 24);
MealsCalculate(0, finish.Hour);
}
// Great Than 1 Day
else
{
// First Day
MealsCalculate(start.Hour, 24);
// Middle Full Days
var days = NumberOfDays(start.Date, finish.Date);
countA += days;
countB += days;
countC += days;
// Finish Day
MealsCalculate(0, finish.Hour);
}
// Total
total = countA + countB + countC;
}
public int NumberOfDays(DateTime start, DateTime finish)
{
var days = 0;
while (start < finish)
{
start.AddDays(1);
days++;
}
return days - 1;
}
public void MealsCalculate(int totalHoursArrived, int totalHoursExit)
{
if (totalHoursArrived <= 8 && totalHoursExit >= 17) //if date is before or on 8AM and leaves on or after 5PM.
{
countA += 1;
countB += 1;
countC += 1;
}
else if (totalHoursArrived <= 8 && (totalHoursExit >= 12 && totalHoursExit < 17)) //if date is before or on 8AM and leaves before 5PM
{
countA += 1;
countB += 1;
}
else if (totalHoursArrived <= 8 && totalHoursExit < 12) //if date is before or on 8AM and leaves before 12PM
{
countA += 1;
}
else if ((totalHoursArrived <= 12 && totalHoursArrived > 8) && totalHoursExit >= 17) //if date is before or on 12PM and leaves on or after 5PM
{
countB += 1;
countC += 1;
}
else if ((totalHoursArrived <= 12 && totalHoursArrived > 8) && totalHoursExit < 17) //if date is before or on 12PM and leaves before 5PM
{
countB += 1;
}
else if (totalHoursArrived >= 17) //if date is after or on 5PM
{
countC += 1;
}
}
}
Related
Okay, I have a load of else if statements, is there a way to condense them into fewer lines of code? Like make one if statement for all of it? And what ways could I make my code more optimize and easier to read?
int x;
int y;
int time=0;
Random rng = new Random();
int hrand_num = rng.Next(-24000, 24000);
int vrand_num = rng.Next(-24000, 24000);
x = hrand_num;
y = vrand_num;
while (true)
{
ConsoleKey key = Console.ReadKey().Key;
if (key == ConsoleKey.UpArrow)
{
y=y+2000;
}
else if (key == ConsoleKey.DownArrow)
{
y=y-2000;
}
else if (key == ConsoleKey.LeftArrow)
{
x = x-1000;
}
else if (key == ConsoleKey.RightArrow)
{
x = x+1000;
}
// Circumnavigate Players Position.
// North and South
if (y >= 24001)
{
y = -24000;
}
else if (y <= -24001)
{
y = 24000;
}
//West and East
else if (x >= 24001)
{
x = -24000;
}
else if (x <= -24001)
{
x = 24000;
}
// Setting Time Zones
if (x >= -2000 && x <= 0 )
{
time = 0;
}
else if (x >=
1 && x <= 2000)
{
time = 1;
}
else if (x >= 2001 && x <=4000)
{
time = 2;
}
else if (x >= 4001 && x <= 6000)
{
time = 3;
}
else if (x >= 6001 && x <= 8000)
{
time = 4;
}
else if (x >= 8001 && x <= 10000)
{
time = 5;
}
else if (x >= 10001 && x <= 12000)
{
time = 6;
}
else if (x >= 12001 && x <= 14000)
{
time = 7;
}
else if (x >= 14001 && x <= 16000)
{
time = 8;
}
else if (x >= 16001 && x <= 18000)
{
time = 9;
}
else if (x >= 18001 && x <= 20000)
{
time = 10;
}
else if (x >= 20001 && x <= 22000)
{
time = 11;
}
else if (x >= 22001 && x <= 24000)
{
time = 12;
}
else if (x == -24000 && x <= -22001)
{
time = 13;
}
else if (x >= -22000 && x <= -20001 )
{
time = 14;
}
else if (x >= -20000 && x <= -18001)
{
time = 15;
}
else if (x >= -18000 && x <= -16001)
{
time = 16;
}
else if (x >= -16000 && x <= -14001)
{
time = 17;
}
else if (x >= -14000 && x <= -12001)
{
time = 18;
}
else if (x >= -12000 && x <= -10001)
{
time = 19;
}
else if (x >= -10000 && x <= -8001)
{
time = 20;
}
else if (x >= -8000 && x <= -6001)
{
time = 21;
}
else if (x >= -6000 && x <= -4001)
{
time = 22;
}
else if (x >= -4000 && x <= -2001)
{
time = 23;
}
Console.WriteLine($"X: {x,6} Y: {y,6} Time: {time,3}");
}
```
Assuming that you are using C# 8.0 you may have a look at the switch statement and switch expressions: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/switch-expression (additionaly the patterns documentation is also helpful: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/patterns)
So you could write something like:
switch (key)
{
case ConsoleKey.UpArrow:
y=y+2000;
break;
// [...]
}
time = x switch
{
>= -2000 and <= 0 => 0,
>= 1 and <= 2000 => 1
// [...]
};
I would suggest that you take advantage of:
a switch statement for interpreting the arrow key
comparing the switch statement to an if loop, you can think of the first case as being the if condition and the remaning cases as being the else if conditions
Math.Abs( ) and Math.Sign( ) for circumnavigating the player's position
Math.Abs( ) returns the absolute value of the variable; e.g. will Math.Abs(x) return 5 both for x = 5 and x = -5
Math.Sign( ) returns the sign of the value; if the value is a negative number, it returns -1; if it's a positive number, it returns 1; if it's neither (0), it returns 0. This helps us determine the wanted sign of the updated value.
a switch expression for setting the time
seeing as the time value alone is determined by x in the end, you can use a switch expression rather than a switch statement to determine its value. The switch expression says that you want to determine the value of time based on the value of x; and each following condition is compared to x (<= -22001 is computed as x <= -22001). If the condition evaluates to true, the provided value is set as the value of time (=> 13 then sets time = 13).
It could be implemented like this:
int x;
int y;
Random rng = new Random();
int hrand_num = rng.Next(-24000, 24000);
int vrand_num = rng.Next(-24000, 24000);
x = hrand_num;
y = vrand_num;
while (true)
{
switch (Console.ReadKey().Key)
{
case ConsoleKey.UpArrow:
y += 2000;
break;
case ConsoleKey.DownArrow:
y -= 2000;
break;
case ConsoleKey.LeftArrow:
x -= 1000;
break;
case ConsoleKey.RightArrow:
x += 1000;
break;
}
// Circumnavigate Players Position.
// North and South
if (Math.Abs(y) > 24000)
{
y = -(Math.Sign(y) * 24000);
}
//West and East
else if (Math.Abs(x) > 24000)
{
x = -(Math.Sign(x) * 24000);
}
// Setting Time Zones
var time = x switch
{
<= -22001 => 13,
<= -20001 => 14,
<= -18001 => 15,
<= -16001 => 16,
<= -14001 => 17,
<= -12001 => 18,
<= -10001 => 19,
<= -8001 => 20,
<= -6001 => 21,
<= -4001 => 22,
<= -2001 => 23,
<= 0 => 0,
<= 2000 => 1,
<= 4000 => 2,
<= 6000 => 3,
<= 8000 => 4,
<= 10000 => 5,
<= 12000 => 6,
<= 14000 => 7,
<= 16000 => 8,
<= 18000 => 9,
<= 20000 => 10,
<= 22000 => 11,
<= 24000 => 12,
_ => 0
};
Console.WriteLine($"X: {x,6} Y: {y,6} Time: {time,3}");
I would also suggest introducing some constants; particularily for the value 24000.
You can use the following to cover all time cases
var time = x <= 24000
? x / 2000 + 1;
: (24000 - x) / 2000 + 13;
how i can get dates ranges list between 2 dates
for example,
start date is 12 February
end date is 23 May
so, the result must be like
12-Feb to 28-Feb
1-Mar to 31-Mar
1-April to 30-April
1-May to 23-May
Let's suppose you are checking only one year, i.e. the current one (2018).
Of course you can make StartDate and EndDate parametric.
There's nothing special in the code below; I used "d-MMMM" as date format since you seemed to ask for the minimum number of days ("d" does that, i.e. selects 1 and not 01 for the first day of a month) and the "long" name of the month ("MMMM" does that, check this answer).
If instead you just want the abbreviation, i.e. "Feb" for "February", you can use "MMM" (check this other answer).
DateTime StartDate = new DateTime(2018, 2, 12);
DateTime EndDate = new DateTime(2018, 5, 23);
for (int i = 0; i <= EndDate.Month - StartDate.Month; i++)
{
DateTime FirstDay = new DateTime(2018, StartDate.Month + i, 1);
if (i == 0)
{
FirstDay = StartDate;
}
DateTime LastDay = new DateTime(2018, StartDate.Month + i, DateTime.DaysInMonth(2018, FirstDay.Month));
if (i == EndDate.Month - StartDate.Month)
{
LastDay = EndDate;
}
Console.WriteLine(FirstDay.ToString("d-MMMM") + " to " + LastDay.ToString("d-MMMM"));
}
Console.ReadLine();
You can also use the following code to make it "cross-year":
static void Main(string[] args)
{
PrintDateList(new DateTime(2018, 2, 12), new DateTime(2018, 5, 23));
PrintDateList(new DateTime(2018, 11, 12), new DateTime(2019, 2, 23));
Console.ReadLine();
}
private static void PrintDateList(DateTime StartDate, DateTime EndDate)
{
Console.WriteLine("");
int TotalMonths = EndDate.Month - StartDate.Month +
(EndDate.Year - StartDate.Year) * 12;
int CurrentYear = StartDate.Year;
int MonthsToSubtract = 0;
for (int i = 0; i <= TotalMonths; i++)
{
int CurrentMonth = StartDate.Month + i;
if (StartDate.Month + i > 12)
{
if ((StartDate.Month + i) % 12 == 1)
{
CurrentYear++;
Console.WriteLine(CurrentYear.ToString());
MonthsToSubtract = StartDate.Month + i - 1;
}
CurrentMonth = StartDate.Month + i - MonthsToSubtract;
}
DateTime FirstDay = new DateTime(CurrentYear, CurrentMonth, 1);
if (i == 0)
{
FirstDay = StartDate;
}
DateTime LastDay = new DateTime(CurrentYear, CurrentMonth, DateTime.DaysInMonth(CurrentYear, FirstDay.Month));
if (i == TotalMonths)
{
LastDay = EndDate;
}
Console.WriteLine(FirstDay.ToString("d-MMMM") + " to " + LastDay.ToString("d-MMMM"));
}
}
The output is
12-February to 28-February
1-March to 31-March
1-April to 30-April
1-May to 23-May
12-November to 30-November
1-December to 31-December
1-January to 31-January
1-February to 23-February
Since you asked, I replaced Console.WriteLine with a List:
private static void PrintDateList(DateTime StartDate, DateTime EndDate)
{
List<Tuple<DateTime>> EventsDatesRangeList = new List<Tuple<DateTime>>();
Console.WriteLine("");
int TotalMonths = EndDate.Month - StartDate.Month +
(EndDate.Year - StartDate.Year) * 12;
int CurrentYear = StartDate.Year;
int MonthsToSubtract = 0;
for (int i = 0; i <= TotalMonths; i++)
{
int CurrentMonth = StartDate.Month + i;
if (StartDate.Month + i > 12)
{
if ((StartDate.Month + i) % 12 == 1)
{
CurrentYear++;
Console.WriteLine(CurrentYear.ToString());
MonthsToSubtract = StartDate.Month + i - 1;
}
CurrentMonth = StartDate.Month + i - MonthsToSubtract;
}
DateTime FirstDay = new DateTime(CurrentYear, CurrentMonth, 1);
if (i == 0)
{
FirstDay = StartDate;
}
DateTime LastDay = new DateTime(CurrentYear, CurrentMonth, DateTime.DaysInMonth(CurrentYear, FirstDay.Month));
if (i == TotalMonths)
{
LastDay = EndDate;
}
Console.WriteLine(FirstDay.ToString("d-MMMM") + " to " + LastDay.ToString("d-MMMM"));
EventsDatesRangeList.Add(new Tuple<DateTime>(FirstDay));
EventsDatesRangeList.Add(new Tuple<DateTime>(LastDay));
}
}
I have a start date and an end date as well as a list of specific dates (holidays).
From the start date to the end date, first I determine if there are any weekends, if there are, I need to determine how many days are weekends and add the number of days to the end date, then determine if any of those dates fall in the list of dates in the holiday list. Again, if a date is in the holiday list, I have to take that number of days, add it to the end and run through the loop again.
For Example. Initial Date Range is 11/20/2017 to 11/24/2017. The first check for weekends would return 0, then I check for holidays, that would return 2 (the 23rd and 24th), I would then need to adjust the dates so my new range is from 11/20 to 11/26, to which I have to loop through weekends again and will find 2 days are in the weekend. Etc. The below code I cheated because I know that there are never more than 2 holidays back to back, but its very cumbersome code.
Also, please consider if the weekends come first, followed by holidays once you adjust for the initial weekend.
I never have an issue with just weekends, it is only for holidays that I am given the wrong value. The code below works fine, I am just looking to see suggestions as to how it can be improved. I have tried for loops, while loops, and this is the only scenario that seems to work. Thanks for your help.
public static int weekends(DateTime start, DateTime end, List<DateTime> holidays, Boolean leftSpace)
{
int days = 0;
DateTime tempstart = start;
TimeSpan startEnd = end - start;
int currentDays = startEnd.Days;
for (DateTime date = start; date <= end; date = date.AddDays(1))
{
int dw = (int)date.DayOfWeek;
if (dw == 0 || dw == 6)
{
days++;
}
}
if (!leftSpace)
{
end = end.AddDays(days);
if (end.DayOfWeek == 0)
{
end = end.AddDays(1);
days++;
}
else if ((int)end.DayOfWeek == 6)
{
end = end.AddDays(2);
days = days + 2;
}
Boolean holidayExist = false;
int holidayCount = 0;
foreach (DateTime holiday in holidays.Where(r => r.Date >= start.Date && r.Date <= end.Date))
{
days++;
holidayCount++;
holidayExist = true;
}
if (holidayExist)
{
DateTime tempend = end;
end = end.AddDays(holidayCount);
int newWeekend = 0;
for (DateTime date = tempend; date <= end; date = date.AddDays(1))
{
int dw = (int)date.DayOfWeek;
if (dw == 0 || dw == 6)
{
days++;
newWeekend++;
}
}
holidayExist = false;
holidayCount = 0;
DateTime holidayEnd = end.AddDays(newWeekend);
foreach (DateTime holiday in holidays.Where(r => r.Date >= end.Date && r.Date <= holidayEnd.Date))
{
days++;
holidayCount++;
holidayExist = true;
}
if (holidayExist)
{
tempend = end;
end = end.AddDays(holidayCount);
for (DateTime date = tempend; date <= end; date = date.AddDays(1))
{
int dw = (int)date.DayOfWeek;
if (dw == 0 || dw == 6)
{
days++;
}
}
}
}
}
return days;
}
I have not tested this for performance but it works. List holidays is a list of dates that are being skipped as they are holidays.
public static int weekends(DateTime start, DateTime end, List<DateTime> holidays)
{
int days = 0;
DateTime tempEnd = end;
TimeSpan startEnd = end - start;
int currentDays = startEnd.Days;
int exclusionDays = 0;
int exclWEOld = 0;
int exclHDOld = 0;
while (currentDays >= 0)
{
int excHolidayTest = exclHolidays(start, tempEnd, holidays);
int excDayTest = exclDays(start, tempEnd);
if (exclusionDays == (excDayTest+ excHolidayTest))
{
break;
}
else
{
exclusionDays = excDayTest + excHolidayTest;
if (exclWEOld == 0 && exclHDOld == 0)
{
tempEnd = tempEnd.AddDays((excDayTest + excHolidayTest));
}
else
{
tempEnd = tempEnd.AddDays((excDayTest - exclWEOld));
tempEnd = tempEnd.AddDays((excHolidayTest - exclHDOld));
}
exclWEOld = excDayTest;
exclHDOld = excHolidayTest;
}
days = excDayTest + excHolidayTest;
currentDays--;
}
return days;
}
public static int exclDays(DateTime start, DateTime end)
{
int exclusionDays = 0;
for (DateTime date = start; date <= end; date = date.AddDays(1))
{
int dw = (int)date.DayOfWeek;
if (dw == 0 || dw == 6)
{
exclusionDays++;
}
}
return exclusionDays;
}
public static int exclHolidays(DateTime start, DateTime end, List<DateTime> holidays)
{
int exclusionHolidays = 0;
foreach (DateTime holiday in holidays.Where(r => r.Date >= start.Date && r.Date <= end.Date))
{
exclusionHolidays++;
}
return exclusionHolidays;
}
I would need to color the days of a months using a datepicker with the following logic: starting from a date in database, i would like to color in orange next 8 days, then next 2 days in green and so on for every following month.
I have the following code but i need a loop:
private void calFecha_DayRender(object source, DayRenderEventArgs e)
{
if (ddloperadores.SelectedValue != "Todos")
{
DataTable asistencia = OperadoresForaneosAsistencia((int)WAPS.Globals.ConvertTo(txtNumOperador.Text, 0)).Tables[0];
if (asistencia.Rows.Count > 0)
{
DataRow iRow = asistencia.Rows[0];
string Tipo = iRow["TipoJornada"].ToString();
Tipo = asistencia.Rows[0]["TipoJornada"].ToString();
if (Tipo == "1") //Tipos de Jornadas
{
DateTime FechaJornada = Convert.ToDateTime(iRow["Jornada_Ini"]);
DateTime fechatemp = DateTime.Today;
DateTime primero = new DateTime(fechatemp.Year, fechatemp.Month, 1);
DateTime ultimo = new DateTime(fechatemp.Year, fechatemp.Month + 1, 1).AddDays(-1);
int counter = 1;
for (DateTime n = FechaJornada; n <= ultimo; n=n.AddDays(1))
{
int rem = counter % 10;
if (rem >= 1 && rem <= 8)
{
e.Cell.BackColor = System.Drawing.Color.DarkGreen;
}
else
{
e.Cell.BackColor = System.Drawing.Color.DarkOrange;
}
counter++;
}
}
}
}
}
calendar image
In reference of your comment do the following in the loop:
int counter = 1;
for(n = FechaJornada; n <= ultimo; n.AddDay(1))
{
int rem = counter % 10;
if (rem >= 1 && rem <= 8)
e.Cell.BackColor = System.Drawing.Color.DarkGreen;
else
e.Cell.BackColor = System.Drawing.Color.DarkOrange;
counter++;
}
EDIT: after moving in dayrender
// compute FechaJornada then...
if(FechaJornada < e.Day.Date)
{
int rem = (e.Day.Date - FechaJornada).Days % 10;
if (rem >= 1 && rem <= 8)
e.Cell.BackColor = System.Drawing.Color.DarkGreen;
else
e.Cell.BackColor = System.Drawing.Color.DarkOrange;
}
else
e.Cell.BackColor = System.Drawing.Color.White;
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I am stuck on this, i need help on how i can ask for user input to enter any year and any month, then that will output a monthly calendar for that specified year and month, i also need to use system.datetime
This is the code i have so far and i dont think it is correct, any help is appreciated. Thanks
class Program
{
static int year = new int();
static int month = new int();
static int[,] calendar = new int[6, 7];
static void Main(string[] args)
{
Console.Write("Enter the year? ");
year = Convert.ToInt32(Console.ReadLine());
Console.Write("Enter the month (January = 1, etc): ");
month = Convert.ToInt32(Console.ReadLine());
DrawHeader();
FillCalendar();
DrawCalendar();
Console.ReadLine();
}
static void DrawHeader()
{
Console.Write("\n\n");
Console.WriteLine("\t" + month);
Console.WriteLine("Mo Tu We Th Fr Sa Su");
}
static void FillCalendar()
{
int days = DateTime.DaysInMonth(year, month);
int currentDay = 1;
for (int i = 0; i < calendar.GetLength(0); i++)
{
for (int j = 0; j < calendar.GetLength(1) && currentDay <= days; j++)
{
if (i == 0 && month > j)
{
calendar[i, j] = 0;
}
else
{
calendar[i, j] = currentDay;
currentDay++;
}
}
}
}
static void DrawCalendar()
{
for (int i = 0; i < calendar.GetLength(0); i++)
{
for (int j = 0; j < calendar.GetLength(1); j++)
{
if (calendar[i, j] > 0)
{
if (calendar[i, j] < 10)
{
Console.Write(" " + calendar[i, j] + " ");
}
else
{
Console.Write(calendar[i, j] + " ");
}
}
else
{
Console.Write(" ");
}
}
Console.WriteLine("");
}
}
}
This should ensure that the day of the month is correctly aligned with the day of the week (i.e. December 1st is a Tuesday)
using System;
using System.Globalization;
namespace Calendar
{
class Program
{
static int year = new int();
static int month = new int();
static int[,] calendar = new int[6, 7];
private static DateTime date;
static void Main(string[] args)
{
Console.Write("Enter the year? ");
year = Convert.ToInt32(Console.ReadLine());
Console.Write("Enter the month (January = 1, etc): ");
month = Convert.ToInt32(Console.ReadLine());
date = new DateTime(year, month, 1);//gives you a datetime object for the first day of the month
DrawHeader();
FillCalendar();
DrawCalendar();
Console.ReadLine();
}
static void DrawHeader()
{
Console.Write("\n\n");
//gives you the month and year at the top of the calendar
Console.WriteLine(CultureInfo.CurrentCulture.DateTimeFormat.GetMonthName(month) + " " + year);
Console.WriteLine("Mo Tu We Th Fr Sa Su");
}
static void FillCalendar()
{
int days = DateTime.DaysInMonth(year, month);
int currentDay = 1;
var dayOfWeek = (int) date.DayOfWeek;
for (int i = 0; i < calendar.GetLength(0); i++)
{
for (int j = 0; j < calendar.GetLength(1) && currentDay - dayOfWeek + 1 <= days; j++)
{
if (i == 0 && month > j)
{
calendar[i, j] = 0;
}
else
{
calendar[i, j] = currentDay - dayOfWeek + 1;
currentDay++;
}
}
}
}
static void DrawCalendar()
{
for (int i = 0; i < calendar.GetLength(0); i++)
{
for (int j = 0; j < calendar.GetLength(1); j++)
{
if (calendar[i, j] > 0)
{
if (calendar[i, j] < 10)
{
Console.Write(" " + calendar[i, j] + " ");
}
else
{
Console.Write(calendar[i, j] + " ");
}
}
else
{
Console.Write(" ");
}
}
Console.WriteLine("");
}
}
}
}
EDIT
If you want to get all the all the dates for a particular day of the week in a chosen month you can do something like this;
var weekDay = 0;
var dates = new List<DateTime>();
for (int i = 0; i < days; i++)
{
if ((int)date.AddDays(i).DayOfWeek == weekDay)
{
dates.Add(date.AddDays(i));
}
}
You would have to ask the user to enter a day of the week and set weekDay to the value they enter. Just remember that Sunday is 0 and Saturday = 6. (I haven't fully tested this though so be careful) - This would have to be entered into your FillCalendar method.