Select Only Fourth Sunday of each month - c#

I am stuck for sometime now, now need your help.
I want to display in a dropdown only fourth Sunday of each month, say from 1-Sep-2010 to 31-Aug-2011
I only want fourth Sunday in dropdown list, how to do it using asp.net C#
Regards

Here is an approach that uses a little LINQ and the knowledge that the fourth Sunday will occur between the 22nd and 28th of a month, inclusive.
DateTime startDate = new DateTime(2010, 9, 1);
DateTime endDate = startDate.AddYears(1).AddDays(-1);
List<DateTime> fourthSundays = new List<DateTime>();
DateTime currentDate = startDate;
while (currentDate < endDate)
{
// we know the fourth sunday will be the 22-28
DateTime fourthSunday = Enumerable.Range(22, 7).Select(day => new DateTime(currentDate.Year, currentDate.Month, day)).Single(date => date.DayOfWeek == DayOfWeek.Sunday);
fourthSundays.Add(fourthSunday);
currentDate = currentDate.AddMonths(1);
}
You can then bind that List<DateTime> to the dropdown or skip the list itself in favor of adding the items as you generate them to the dropdown, like below.
yourDropdown.Items.Add(new ListItem(fourthSunday.ToString()));
For giggles, you can do the whole thing in a LINQ statement and skip (most of) the variables.
DateTime startDate = new DateTime(2010, 9, 1);
IEnumerable<DateTime> fourthSundays =
Enumerable.Range(0, 12)
.Select(item => startDate.AddMonths(item))
.Select(currentMonth =>
Enumerable.Range(22, 7)
.Select(day => new DateTime(currentMonth.Year, currentMonth.Month, day))
.Single(date => date.DayOfWeek == DayOfWeek.Sunday)
);

Got bored so here you go. Two helper methods one retrieves the Week if it exist, and the other iterates through the months
class Program
{
static void Main(string[] args)
{
DateTime startDate = new DateTime(2010, 09, 1);
foreach(DateTime dt in EachMonth( new DateTime(2010, 09, 1), new DateTime(2011, 09, 1))){
DateTime? result = GetDayByWeekOffset(DayOfWeek.Sunday, dt, 4);
Console.WriteLine("Sunday:" + (result.HasValue?result.Value.ToString("MM-dd-yyyy"):"null"));
}
Console.ReadKey();
}
public static DateTime? GetDayByWeekOffset(DayOfWeek day, DateTime month, int weekOffSet)
{
//First day of month
DateTime firstDayOfMonth = month.AddDays((-1 * month.Day) + 1);
//
int daysOffSet;
daysOffSet= ((int)day + 7 - (int)firstDayOfMonth.DayOfWeek) % 7;
DateTime firstDay = month.AddDays(daysOffSet);
// Add the number of weeks specified
DateTime resultDate = firstDay.AddDays((weekOffSet - 1) * 7);
if (resultDate.Month != firstDayOfMonth.Month){
return null;
}else{
return resultDate;
}
}
public static IEnumerable<DateTime> EachMonth(DateTime from, DateTime thru)
{
for (var month = from.Date; month.Date <= thru.Date; month = month.AddMonths(1))
yield return month;
}
}

Anthony's answer above is nice, I like it a lot. As an alternate, here is a method which is parameterized for the day of the week and the week number (i.e. if you need other combinations, like 4th Sunday, 3rd Friday, etc.) with some comments.
Call it like this for your case:
List<DateTime> sundays = DateInstances(new DateTime(2010, 9, 1), new DateTime(2011, 8, 31), DayOfWeek.Sunday, 4);
And the method itself:
public List<DateTime> DateInstances(DateTime start, DateTime end, DayOfWeek day, int weeks)
{
if (start > end)
throw new ArgumentOutOfRangeException("end", "The start date must occur before the end date");
List<DateTime> results = new List<DateTime>();
DateTime temp = start;
while (temp < end)
{
DateTime firstWeekday = new DateTime(temp.Year, temp.Month, 1);
//increment to the given day (i.e. if we want the 4th sunday, we must find the first sunday of the month)
while (firstWeekday.DayOfWeek != day)
firstWeekday = firstWeekday.AddDays(1);
//add the number of weeks (note: we already have the first instance, so subtract 1)
firstWeekday = firstWeekday.AddDays(7 * (weeks - 1));
//make sure we haven't gone over to the next month
if (firstWeekday.Month == temp.Month)
results.Add(firstWeekday);
//let's not loop forever ;)
temp = temp.AddMonths(1);
}
return results;
}

Related

Week difference between 2 dates in C#

I'm trying to make a function in C# that returns the week difference between two dates. Its goal is to provide the same result of:
select datediff(ww,'2018-04-13','2018-04-16') as diff
In the example above there is only 3 days between these dates, but they are in different weeks, so the result should be 1.
I've tried to use .TotalDays but it's not working properly. I also tried .GetWeekOfYear but it won't return correctly when the year of the dates are different. I've seem many questions here on StackOverflow and on other forums and so far none of them match my case. This is the function I'm trying to far:
public static int GetWeekDiff(DateTime dtStart, DateTime dtEnd) {
// Doesn't work
var val = ((dtEnd - dtStart).TotalDays / 7);
val = Math.Ceiling(val);
return Convert.ToInt32(val);
// Doesn't work well between years
DateTimeFormatInfo dinfo = DateTimeFormatInfo.CurrentInfo;
var x = dinfo.Calendar.GetWeekOfYear(dtStart, CalendarWeekRule.FirstFullWeek, DayOfWeek.Monday);
var y = dinfo.Calendar.GetWeekOfYear(dtEnd, CalendarWeekRule.FirstFullWeek, DayOfWeek.Monday);
return y - x;
}
In the first part of my function, I tried what is described in this post. It didn't work
Can you help me?
Thanks in advance.
First figure how many days there are between the two dates. Divide the number of days by 7 to get full weeks.
Now figure out if there's an extra week to be counted by finding taking the number of days modulus 7 to get any remaining days. If the first date plus remaining days falls in a different week, add an extra week on to the count.
void Main()
{
var first = new DateTime(2018, 04, 13);
var second = new DateTime(2018, 04, 16);
Console.WriteLine(weekDiff(first, second));
}
public int weekDiff(DateTime d1, DateTime d2, DayOfWeek startOfWeek = DayOfWeek.Monday)
{
var diff = d2.Subtract(d1);
var weeks = (int)diff.Days / 7;
// need to check if there's an extra week to count
var remainingDays = diff.Days % 7;
var cal = CultureInfo.InvariantCulture.Calendar;
var d1WeekNo = cal.GetWeekOfYear(d1, CalendarWeekRule.FirstFullWeek, startOfWeek);
var d1PlusRemainingWeekNo = cal.GetWeekOfYear(d1.AddDays(remainingDays), CalendarWeekRule.FirstFullWeek, startOfWeek);
if (d1WeekNo != d1PlusRemainingWeekNo)
weeks++;
return weeks;
}
static void Main(string[] args)
{
DateTime date1 = new DateTime(2018, 04, 18);
DateTime date2 = new DateTime(2018, 04, 19);
System.Console.WriteLine((GetDiff(new DateTime(2018, 04, 18), new DateTime(2018, 04, 18)))); // 0
System.Console.WriteLine((GetDiff(new DateTime(2018, 04, 22), new DateTime(2018, 04, 23)))); // 1
System.Console.WriteLine((GetDiff(new DateTime(2018, 04, 16), new DateTime(2018, 04, 22)))); // 0
System.Console.WriteLine((GetDiff(new DateTime(2018, 04, 18), new DateTime(2018, 05, 03)))); // 2
}
private static int GetDiff(DateTime date1, DateTime date2)
{
date1 = SetDayToMonday(date1);
date2 = SetDayToMonday(date2);
return (int)((date2 - date1).TotalDays / 7);
}
private static DateTime SetDayToMonday(DateTime date)
{
var weekDay = date.DayOfWeek;
if (weekDay == DayOfWeek.Sunday)
return date.AddDays(-6);
else
return date.AddDays(-((int)weekDay-1));
}
First, set the day to the monday of the current week. Then count all full weeks(= /7 days as int). Easy as it is, it works probably across weeks and years.
See if this works. There could be more use cases that this doesn't cover, and the solution depends on how you define a week boundary (this assumes Sunday-Monday based on a comment above).
// Output:
// Weeks between 12/28/2017 and 1/10/2018: 2
// Weeks between 4/13/2018 and 4/16/2018: 1
// Weeks between 4/21/2018 and 4/22/2018: 0
// Weeks between 4/22/2018 and 4/23/2018: 1
void Main()
{
var datePairs = new List<KeyValuePair<DateTime, DateTime>>();
datePairs.Add(new KeyValuePair<DateTime, DateTime>(new DateTime(2017, 12, 28), new DateTime(2018, 1, 10)));
datePairs.Add(new KeyValuePair<DateTime, DateTime>(new DateTime(2018, 4, 13), new DateTime(2018, 4, 16)));
datePairs.Add(new KeyValuePair<DateTime, DateTime>(new DateTime(2018, 4, 21), new DateTime(2018, 4, 22)));
datePairs.Add(new KeyValuePair<DateTime, DateTime>(new DateTime(2018, 4, 22), new DateTime(2018, 4, 23)));
foreach (var datePair in datePairs)
{
var string1 = datePair.Key.ToShortDateString();
var string2 = datePair.Value.ToShortDateString();
Console.WriteLine($"Weeks between {string1} and {string2}: {GetWeekDiff(datePair.Key, datePair.Value)}");
}
}
public static int GetWeekDiff(DateTime dtStart, DateTime dtEnd)
{
var totalDays = (dtEnd - dtStart).TotalDays;
var weeks = (int)totalDays / 7;
var hasRemainder = totalDays % 7 > 0;
if (hasRemainder)
{
if (!(dtStart.DayOfWeek.Equals(DayOfWeek.Saturday) && dtEnd.DayOfWeek.Equals(DayOfWeek.Sunday)))
{
weeks++;
}
}
return weeks;
}
Maybe it can help
public static int GetIso8601WeekOfYear(DateTime time)
{
// Seriously cheat. If its Monday, Tuesday or Wednesday, then it'll
// be the same week# as whatever Thursday, Friday or Saturday are,
// and we always get those right
DayOfWeek day = CultureInfo.InvariantCulture.Calendar.GetDayOfWeek(time);
if (day >= DayOfWeek.Monday && day <= DayOfWeek.Wednesday)
{
time = time.AddDays(3);
}
// Return the week of our adjusted day
return CultureInfo.InvariantCulture.Calendar.GetWeekOfYear(time, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday);
}
Get the correct week number of a given date
Can't comment yet and already used a flag on this post on something I believed to be similar. Here is another post I found that appears to align with the solution you are trying to create:
Get the number of calendar weeks between 2 dates in C#
This is my implementation to solve a similar problem, I haven't tested in thoroughly but it seems to work.
var dt1 = DateTime.Today.AddDays(-30);
var dt2 = DateTime.Today;
var noOfDays =(int) (dt2 - dt1).TotalDays;
int reminder;
var weeks = Math.DivRem(noOfDays, 7, out reminder);
weeks = reminder > 0 ? weeks + 1 : weeks;
It returns 1 week for 6 days or less gap, which is exactly what I needed.

How to find exact date range from list of date ranges by entering single date

I want to find the date range which falls in input date, following is structure
public class Duration
{
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
}
var durations = new List<Duration>();
var duration1 = new Duration()
{
StartDate = new DateTime(2017, 08, 1),
EndDate = new DateTime(2017, 08, 10)
};
durations.Add(duration1);
var duration2 = new Duration()
{
StartDate = new DateTime(2017, 08, 5),
EndDate = new DateTime(2017, 08, 10)
};
durations.Add(duration2);
var duration3 = new Duration()
{
StartDate = new DateTime(2017, 08, 5),
EndDate = new DateTime(2017, 08, 6)
};
durations.Add(duration3);
Now I want to find duration which is closest to the entered date for list of <Durations> with LINQ or for-loop
My expected result for currentDate=new DateTime(2017, 08, 7); is duration2
You first need to check if the currentDate is within the start and end dates of each range. For the ones that meet that condition, you calculate the "closeness" adding both distances. When you find one lapse(gap) smaller tan the previous, you save its index... and voilá
int lapse = Integer.MaxValue;
int counter = 0;
int index = 0;
foreach (d in durations) {
if (((d.StartDate <= currentDate) && (d.EndDate >= currentDate))) {
int newlapse = ((currentDate - d.StartDate).TotalDays + (d.EndDate - currentDate).TotalDays);
if ((newlapse < lapse)) {
lapse = newlapse;
index = counter;
}
}
counter +=1;
}
return durations(index);
If you need the middle of interval to be closest:
durations.OrderBy((d) => Math.Abs(d.EndDate.Ticks + d.StartDate.Ticks) / 2 - currentDate.Ticks).FirstOrDefault();
If you need the start of interval to be closest:
durations.OrderBy((d) => Math.Abs(d.EndDate.Ticks - currentDate.Ticks)).FirstOrDefault();
As D le mentioned above
First check if currentDate is within the start and end dates
Second select the duration with the minimal difference between start end end date
I used a nuget package called morelinq which gives nice extensions methods like MinBy:
var result = (from d in durations
where (d.StartDate <= currentDate && d.EndDate >= currentDate)
select d).MinBy(d => d.EndDate - d.StartDate);

How to get date of a day in a week in C#

I am trying to get Date of a specific day based on its sequence in a week like
GetDate(22, 4);
which needs to return the date of 4th day in 22nd weeks of current year. How can I do this?
void Main()
{
int months;
var year = DateTime.Now.ToString("yyyy");
months = GetWeeksInYear( Convert.ToInt32(year));
Console.WriteLine(months);
}
public int GetWeeksInYear(int year)
{
DateTimeFormatInfo dfi = DateTimeFormatInfo.CurrentInfo;
DateTime date1 = new DateTime(year, 12, 31);
Calendar cal = dfi.Calendar;
return cal.GetWeekOfYear(date1, dfi.CalendarWeekRule, dfi.FirstDayOfWeek);
}
public int GetDate(int weekNo, int dayNo)
{
return // Date
}
You can just add the number of days from the beginning of the year:
var dt = new DateTime(year, 1, 1);
dt = dt.AddDays(weekNo * 7 + dayNo);
var date = dt.Date;
I think a simple way would be to take Jan 1 of year and add number of days,
DateTime day = new DateTime(year, 1, 1).AddDays((week * 7) + days);
firstable the week of the year is a calendar calculation and locale dependent value so you have to consider that when giving the week number...
So you are for sure missing the use of something like
CultureInfo.CurrentCulture.Calendar;

How to find all certain days of week in the given year?

My task is to find all Friday, 13 in a year that user inputs.
Can somebody explain how to do it? (I'm a beginner in c#)
int year = 2015;
for(int m=1; m<=12; m++)
{
var dt = new DateTime(year, m, 13);
if (dt.DayOfWeek == DayOfWeek.Friday)
Console.WriteLine(dt.ToShortDateString());
}
To obtain the dates you may use Linq:
var dates = Enumerable
.Range(1, 12) // All months
.Select(month => new DateTime(2015, month, 13))
.Where(date => date.DayOfWeek == DayOfWeek.Friday);
To print out them
Console.WriteLine(String.Join(Environment.NewLine, dates));
If you want to get these dates in Gregorian Calender, you can use a combination of a loop, DateTime constructor and DayOfWeek enumeration like;
int year = 2015;
for (int i = 1; i < 13; i++)
{
if(new DateTime(year, i, 13).DayOfWeek == DayOfWeek.Friday)
Console.WriteLine(new DateTime(year, i, 13));
}
For 2015, result will be;
13.02.2015 00:00:00
13.03.2015 00:00:00
13.11.2015 00:00:00
If you want to number of months, you can use .Month property of the result like;
Console.WriteLine((new DateTime(year, i, 13)).Month);
If you want to get your month names based on your CurrentCulture, you can use custom MMMM specifier like;
Console.WriteLine((new DateTime(year, i, 13)).ToString("MMMM"));
Also you can use Enumerable.Range like;
List<int> monthList = Enumerable.Range(1, 12).
Where(d => new DateTime(2015, d, 13).DayOfWeek == DayOfWeek.Friday).
ToList(); // {2, 3, 11}
or
List<string> monthList = Enumerable.Range(1, 12).
Where(d => new DateTime(2015, d, 13).DayOfWeek == DayOfWeek.Friday).
Select(m => new DateTime(2015, m, 13).ToString("MMMM", CultureInfo.InvariantCulture)).
ToList(); // {February, March, November}
Try to inspire by the code showed in that thread:
Finding every friday from start date till the end of the year
(of course you will have to check if selected Friday is 13th)
It can be done like this using linq.
var year = 2015;
var months = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
var unluckyDays = months.Select(m => new DateTime(year, m, 13)).Where(dt => dt.DayOfWeek == DayOfWeek.Friday);
The first Select statement projects the list of integers into a list of datetimes representing the 13th of each month in the year specified.
Then simply filter this list to those where the day of the week is Friday.
DateTime objects have a property on them called DayOfWeek. You can utilize this to help you figure out if a date supplied returns a DayOfWeek Value of Friday: see below:
static void Main(string[] args)
{
for (var i = 1; i < 12; i++)
{
DateTime date = new DateTime(2015, i, 13);
if (date.DayOfWeek == DayOfWeek.Friday)
Console.WriteLine(date.ToShortDateString());
}
Console.ReadLine();
}
Yes, it is quite simple
int year = 2014;
DateTime day = new DateTime(2014,1,1);
while (day.Year == year)
{
if (day.DayOfWeek == DayOfWeek.Friday && day.Day == 13)
{
Console.WriteLine(day);
}
day = day.AddDays(1);
}
You init a DateTime variable in the start of the year
Then you loop over each day of the year in this code I printed it
You can find more info of the DateTime class here
DateTime Day of the week
DateTime referenc in MSDN

Get Date List from weeknumber c#

I have a function that get the current weeknumber from the given date
e.g.
GregorianCalendar cal = new GregorianCalendar(GregorianCalendarTypes.Localized);
return cal.GetWeekOfYear(date, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday);
gives back weeknumber 40 for DateTime.Now.
So my question is , also my problem, i need to get the dates in the returned week. I've tried several thing and none so for worked.
You can use the class Week of the Time Period Library for .NET:
Week week = new Week( new DateTime( 2012, 03, 21 ) );
Console.WriteLine( "week #: ", week.WeekOfYear );
Console.WriteLine( "week first day: ", week.FirstDayOfWeek );
Console.WriteLine( "week last day: ", week.LastDayOfWeek );
Additional, the class Week supports ISO 8601 week numbering and custom cultures.
You could use this function to get the first date of a week:
public static DateTime FirstDateOfWeek(int year, int weekOfYear)
{
DateTime jan1 = new DateTime(year, 1, 1);
int daysOffset = Convert.ToInt32(System.Globalization.CultureInfo.CurrentCulture.DateTimeFormat.FirstDayOfWeek) - Convert.ToInt32(jan1.DayOfWeek);
DateTime firstWeekDay = jan1.AddDays(daysOffset);
System.Globalization.CultureInfo curCulture = System.Globalization.CultureInfo.CurrentCulture;
int firstWeek = curCulture.Calendar.GetWeekOfYear(jan1, curCulture.DateTimeFormat.CalendarWeekRule, curCulture.DateTimeFormat.FirstDayOfWeek);
if (firstWeek <= 1) {
weekOfYear -= 1;
}
return firstWeekDay.AddDays(weekOfYear * 7);
}
Then you can get all dates in this week in the following way:
var firstDate = FirstDateOfWeek(2012, 40);
var allWeekDays = new List<DateTime>();
allWeekDays.Add(firstDate);
var currentDate = firstDate;
for(int d = 1; d < 7; d++)
{
currentDate=currentDate.AddDays(1);
allWeekDays.Add(currentDate);
}
or in one line:
var week = Enumerable.Range(0,7).Select(d => firstDate.AddDays(d)).ToList();
You can get the first and last day in the week simply by looking at the weekday of the given date, and look for the monday:
DateTime firstDay = date.Date;
while (firstDay.DayOfWeek != DayOfWeek.Monday) {
firstDay = date.AddDays(-1);
}
DateTime lastDay = firstDay.AddDays(6);

Categories