I have a function that returns me only the fridays from a range of dates
public static List<DateTime> GetDates(DateTime startDate, int weeks)
{
int days = weeks * 7;
//Get the whole date range
List<DateTime> dtFulldateRange = Enumerable.Range(-days, days).Select(i => startDate.AddDays(i)).ToList();
//Get only the fridays from the date range
List<DateTime> dtOnlyFridays = (from dtFridays in dtFulldateRange
where dtFridays.DayOfWeek == DayOfWeek.Friday
select dtFridays).ToList();
return dtOnlyFridays;
}
Purpose of the function: "List of dates from the Week number specified till the StartDate i.e. If startdate is 23rd April, 2010 and the week number is 1,then the program should return the dates from 16th April, 2010 till the startddate".
I am calling the function as:
DateTime StartDate1 = DateTime.ParseExact("20100430", "yyyyMMdd", System.Globalization.CultureInfo.InvariantCulture);
List<DateTime> dtList = Utility.GetDates(StartDate1, 4).ToList();
Now the requirement has changed a bit. I need to find out only the last Fridays of every month.
The input to the function will remain same.
You already have the list of Fridays in the given range. Now just query this again like this:
List<DateTime> lastFridays = (from day in fridays
where day.AddDays(7).Month != day.Month
select day).ToList<DateTime>();
Hope this helps.
Just a small improvement on Sarath's answer, for those (like me) who step into this question
private DateTime GetLastFridayOfTheMonth(DateTime date)
{
var lastDayOfMonth = new DateTime(date.Year, date.Month, DateTime.DaysInMonth(date.Year, date.Month));
while (lastDayOfMonth.DayOfWeek != DayOfWeek.Friday)
lastDayOfMonth = lastDayOfMonth.AddDays(-1);
return lastDayOfMonth;
}
Here's an extension method we are using.
public static class DateTimeExtensions
{
public static DateTime GetLastFridayInMonth(this DateTime date)
{
var firstDayOfNextMonth = new DateTime(date.Year, date.Month, 1).AddMonths(1);
int vector = (((int)firstDayOfNextMonth.DayOfWeek + 1) % 7) + 1;
return firstDayOfNextMonth.AddDays(-vector);
}
}
Below is the MbUnit test case
[TestFixture]
public class DateTimeExtensionTests
{
[Test]
[Row(1, 2011, "2011-01-28")]
[Row(2, 2011, "2011-02-25")]
...
[Row(11, 2011, "2011-11-25")]
[Row(12, 2011, "2011-12-30")]
[Row(1, 2012, "2012-01-27")]
[Row(2, 2012, "2012-02-24")]
...
[Row(11, 2012, "2012-11-30")]
[Row(12, 2012, "2012-12-28")]
public void Test_GetLastFridayInMonth(int month, int year, string expectedDate)
{
var date = new DateTime(year, month, 1);
var expectedValue = DateTime.Parse(expectedDate);
while (date.Month == month)
{
var result = date.GetLastFridayInMonth();
Assert.AreEqual(expectedValue, result);
date = date.AddDays(1);
}
}
}
Check what day of the week the first day of the next month is on, then subtract enough days to get a Friday.
Or, if you already have a list of Fridays, return only those for which adding 7 days gives a date in the next month.
Based on DeBorges answer, here is an extension to get any specific Day
public static DateTime GetLastSpecificDayOfTheMonth(this DateTime date, DayOfWeek dayofweek)
{
var lastDayOfMonth = new DateTime(date.Year, date.Month, DateTime.DaysInMonth(date.Year, date.Month));
while (lastDayOfMonth.DayOfWeek != dayofweek)
lastDayOfMonth = lastDayOfMonth.AddDays(-1);
return lastDayOfMonth;
}
Call the below function by sending the date as parameter, in which it extracts the month and year from the date parameter and returns the last Friday of that month
public DateTime GetLastFridayOfMonth(DateTime dt)
{
DateTime dtMaxValue = DateTime.MaxValue;
DateTime dtLastDayOfMonth = new DateTime(dt.Year, dt.Month, DateTime.DaysInMonth(dt.Year, dt.Month));
while (dtMaxValue == DateTime.MaxValue)
{
// Returns if the decremented day is the fisrt Friday from last(ie our last Friday)
if (dtMaxValue == DateTime.MaxValue && dtLastDayOfMonth.DayOfWeek == DayOfWeek.Friday)
return dtLastDayOfMonth;
// Decrements last day by one
else
dtLastDayOfMonth = dtLastDayOfMonth.AddDays(-1.0);
}
return dtLastDayOfMonth;
}
Related
This question already has answers here:
How to get last Friday of month(s) using .NET
(6 answers)
Closed 4 years ago.
I'm writing a method that returns the last saturday of the month
public static DateTime LastDayOfTheMOnth(DateTime Date)
I don't know how to start, in java is simple but in c# is more dificult
You can add a month to the current day and go backwards from there.
Taken from here.
I've made it as an extension method so that you can call it from the DateTimeobject itself.
public static DateTime LastThursday(this DateTime time)
{
DateTime date = new DateTime(time.Year, time.Month, 1).AddMonths(1).AddDays(-1);
while (date.DayOfWeek != DayOfWeek.Thursday) {
date = date.AddDays(-1);
}
return date;
}
Can be called like
DateTime x = new DateTime(2019, 4, 22);
Console.WriteLine(x.LastThursday());
First you need to get list of Saturday in specific month
var daysInMonth = DateTime.DaysInMonth(year, month);
List<DateTime> list = new List<DateTime>();
for (int day = daysInMonth; day > 0; day--)
{
DateTime currentDateTime = new DateTime(year, month, day);
if (currentDateTime.DayOfWeek == DayOfWeek.Saturday)
{
list.Add(currentDateTime);
}
}
secondly, use linq to get last Saturday from the list
var result = list.OrderByDescending(d => d.Date).First();
Console.WriteLine(result);
note: you can change DayOfWeek.Saturday to any day you want
Working example
You can use:
public static DateTime LastThursdayOfTheMonth(int month, int year)
{
DateTime date = new DateTime(year, month, DateTime.DaysInMonth(year, year));
while (date.DayOfWeek != DayOfWeek.Thursday)
{
date = date.AddDays(-1);
}
return date;
}
Regards, LA.
How to calculate actual working days of my when user checkin in hotel? I want to count working days only except Saturday and Sunday. Please check below function its count working days but in parameter I entered startdate and enddate.
I want send only startdate its automatically count 15 working days and return me enddate.
//Days count
public static double GetBusinessDays(DateTime startD, DateTime endD)
{
double calcBusinessDays =
1 + ((endD - startD).TotalDays * 5 -
(startD.DayOfWeek - endD.DayOfWeek) * 2) / 7;
if (endD.DayOfWeek == DayOfWeek.Saturday) calcBusinessDays--;
if (startD.DayOfWeek == DayOfWeek.Sunday) calcBusinessDays--;
return calcBusinessDays;
}
I want like this:
public static Datetime GetBusinessDays(DateTime startDate)
{
Datetime After15WorkingDaysDate;
return After15WorkingDaysDate;
}
Here are two methods.
The idea is to generate each date in the range, decide whether it is a Business Day, and only then add it to the result list.
GetBusinessDaysInRange returns a list of the dates of the Business Days between the given start and end date. End date is exclusive, i.e. if the end date is a Business Day, it will not be part of the result.
// Returns a list of the dates of the Business Days between the given start and end date
public static IEnumerable<DateTime> GetBusinessDaysInRange(DateTime startDate, DateTime endDate, DayOfWeek[] closedOn) {
if (endDate < startDate) {
throw new ArgumentException("endDate must be before startDate");
}
var businessDays = new List<DateTime>();
var date = startDate;
while (date < endDate) {
if (!closedOn.Contains(date.DayOfWeek)) {
businessDays.Add(date);
}
date = date.AddDays(1);
}
return businessDays;
}
GetFixedNumberOfBusinessDays returns a list of the dates of the Business Days from the given start with the given number of days (the method you asked for).
// Returns a list of the dates of the Business Days from the given start with the given number of days
public static IEnumerable<DateTime> GetFixedNumberOfBusinessDays(DateTime startDate, int numberOfBusinessDays, DayOfWeek[] closedOn) {
if (numberOfBusinessDays < 0) {
throw new ArgumentException("numberOfBusinessDays must be zero or positive.");
}
var businessDays = new List<DateTime>();
var date = startDate;
while (businessDays.Count() < numberOfBusinessDays) {
if (!closedOn.Contains(date.DayOfWeek)) {
businessDays.Add(date);
}
date = date.AddDays(1);
}
return businessDays;
}
The parameter DayOfWeek[] closedOn was introduced because you do not want to hardcode the days of the week that are not Business Days.
The return type was changed to IEnumerable<DateTime> so this method is more universal. If you only want the number of days and are not interested in the actual dates, just run a .Count() on the result. If you want the end date, call .Last().
.Net Fiddle with usage examples:
var closedOn = new DayOfWeek[] { DayOfWeek.Saturday, DayOfWeek.Sunday };
var start = new DateTime(2018, 07, 23);
var numberOfDays = 10;
var businessDays = GetFixedNumberOfBusinessDays(end, numberOfDays, closedOn);
int actualNumberOfBusinessDays = businessDays.Count(); // 10
DateTime endDate = businessDays.Last(); // Friday, August 3, 2018
It should be generic method. You can add different work day in another place.
public static DateTime AddWorkdays(this DateTime originalDate, int workDays)
{
DateTime tmpDate = originalDate;
while (workDays > 0)
{
tmpDate = tmpDate.AddDays(1);
if (tmpDate.DayOfWeek == DayOfWeek.Saturday ||
tmpDate.DayOfWeek == DayOfWeek.Sunday )
workDays--;
}
return tmpDate;
}
DateTime endDate = startDate.AddWorkdays(15);
i want c# code for getting Last Date of week for given month and year.
suppose given month is 1 and year is 2016 then method should return me
--01/02/2016
--01/09/2016
--01/16/2016
--01/23/2016
--01/30/2016
--02/06/2016
So you want a method which takes a year and a month as parameter and returns dates. Those dates should be the last dates of all weeks in that month, optionally also of following months.
This should work then:
public static IEnumerable<DateTime> GetLastWeekDatesOfMonth(int year, int month, DayOfWeek firstDayOfWeek = DayOfWeek.Monday, bool includeLaterMonths = false)
{
DateTime first = new DateTime(year, month, 1);
int daysOffset = (int)firstDayOfWeek - (int)first.DayOfWeek;
if (daysOffset < 0)
daysOffset = 7 - Math.Abs(daysOffset);
DateTime firstWeekDay = first.AddDays(daysOffset);
DateTime current = firstWeekDay.AddDays(-1); // last before week start
if (current.Month != month)
current = current.AddDays(7);
yield return current;
if (includeLaterMonths)
{
while (true)
{
current = current.AddDays(7);
yield return current;
}
}
else
{
while((current = current.AddDays(7)).Month == month)
yield return current;
}
}
Your sample:
var lastDates = GetLastWeekDatesOfMonth(2016, 1, DayOfWeek.Sunday, true);
foreach (DateTime dt in lastDates.Take(6))
Console.WriteLine(dt.ToShortDateString());
public static DateTime GetLastDateofWeek(int yr, int mnth, int week)
{
DateTime dt = new DateTime(yr, mnth, 1);
DateTime newdate = new DateTime();
if (dt.DayOfWeek == DayOfWeek.Monday)
{
newdate = dt.AddDays(((week - 1) * 7) + 5);
}
else
{
newdate = dt.AddDays((8 - (int)dt.DayOfWeek) % 7 + ((week - 2) * 7) + 5);
}
return newdate;
}
First get month and year, example:
int year = 2016;
int month = 1;
And then create a new instance of the DateTime class that represents the first saturday.
DateTime firstsaturday = new DateTime(year,month,1);
while(firstsaturday.DayOfWeek != DayOfWeek.Saturday)
{
firstsaturday = firstsaturday.AddDays(1);
]
Then create a List of DateTime values.
List<DateTime> saturdays = new List<DateTime>();
saturdays.Add(firstsaturday);
And then cycle through all saturdays using a loop.
DateTime CurrentSaturday = firstsaturday;
while(CurrentSaturday.AddDays(7).Month == month)
{
CurrentSaturday = CurrentSaturday.AddDays(7);
Saturdays.Add(CurrentSaturday);
}
You may try this code.
using System;
public class Program
{
public static void Main()
{
DateTime thisMonthInLastYear = DateTime.Now.AddYears(-1);
DateTime endOfMonth = new DateTime(thisMonthInLastYear.Year,
thisMonthInLastYear.Month,
DateTime.DaysInMonth(thisMonthInLastYear.Year,
thisMonthInLastYear.Month));
Console.WriteLine("Today : "+DateTime.Now.ToString("dd-MM-yyyy"));
Console.WriteLine("This Month in last years : "+endOfMonth.ToString("dd-MM-yyyy"));
Console.WriteLine("Next month in last years : "+endOfMonth.AddMonths(1).ToString("dd-MM-yyyy"));
}
}
I have a what seems like simple date issue and I just can't wrap my head around trying to get it efficiently... I basically need to get the previous months date for a specific day.
For example: If today is the 3rd Thursday of the month, I want to get the 3rd Thursday's date of last month. Its important that its based of the number of the day...ie: First Monday, 4th Friday, 2nd Wednesday, etc.
What's the best way to get this done?
BTW...If there is not an equivalent previous months day that is fine. I can handle that. Also, currently I am counting the number or days ("Mondays", "Tuesdays", etc) manually to figure this out. I was just hoping there is a more elegant way to do it.
Here's what I would do:
static DateTime? GetLastMonthSameNthDayOfWeek(DateTime date)
{
int nth = (date.Day-1) / 7; // returns 0 if 1st, 1 if 2nd...
var prevMonthDay = date.AddMonths(-1);
// find the first date of month having the same day of week
var d = new DateTime(prevMonthDay.Year, prevMonthDay.Month, 1);
while(d.Day <= 7)
{
if (d.DayOfWeek == date.DayOfWeek)
break;
d = d.AddDays(1);
}
// go to nth day of week
d = d.AddDays(7 * nth);
// if we have passed the current month, there's no nth day of week
if (d.Month != prevMonthDay.Month)
return null;
return d;
}
Usage example:
// 3rd wednesday of August 2012
var a = new DateTime(2012, 8, 15);
var aPrev = GetLastMonthSameNthDayOfWeek(a);
// aPrev = July 18th 2012 (i.e. the 3rd wednesday of July 2012)
// 5th wednesday of August 2012
var b = new DateTime(2012, 8, 15);
var bPrev = GetLastMonthSameNthDayOfWeek(b);
// bPrev = null, because there's no 5th wednesday of July 2012
N.B. :
getting the ordinal position of the day of week inside a month is really easy:
int nth = ((date.Day-1) / 7) + 1; // 1 -> 1st, 2 -> 2nd, 3 -> 3rd ...
As I couldn't find a built-in way, I've written this simple extension method for DateTime, check it out:
public static class DateTimeExtension
{
public static DateTime GetPositionalDate(this DateTime BaseDate, DayOfWeek WeekDay, int position)
{
if (position < 1)
{
throw new Exception("Invalid position");
}
else
{
DateTime ReturnDate = new DateTime(BaseDate.Year, BaseDate.Month, BaseDate.Day);
int PositionControl = 1;
bool FoundDate = false;
while(ReturnDate.DayOfWeek != WeekDay)
{
ReturnDate = ReturnDate.AddDays(1);
}
while (!FoundDate && PositionControl <= position)
{
PositionControl++;
if (PositionControl == position)
{
FoundDate = true;
}
else
{
ReturnDate = ReturnDate.AddDays(7);
}
}
if (FoundDate)
{
return ReturnDate;
}
else
{
throw new Exception("Date not found");
}
}
}
}
Usage:
DateTime lastMonth = DateTime.Now.GetPositionalDate(DayOfWeek.Sunday, 2);
Regards
There is no, by default, a way that .Net understand this specific logic for dates. So using the following, you can get what you're looking for:
var now = DateTime.Now.Date;
Use DateTime.AddMonth(-1) to get last month.
Use DateTime.AddDays(now.Days * -1 + 1) to get the first of the month.
Use DateTime.DayOfWeek to determine the day and subtract or add days as necessary
Ok, what you can do is determine the day of the week of the first day of the month last month, take the difference between the day of the week you want and that day of the week, then add 7 * the weeks you want (less one week)...
// Let's get the 3rd Friday of last month:
// get starting date
DateTime date = new DateTime();
// get first day of last month
DateTime firstOfLastMonth = date.AddMonths(-1).AddDays(-1 * (date.Day + 1));
// subtract out the day of the week (get the previous Sunday, even if it is last month)
DateTime justBeforeMonth = firstOfLastMonth.AddDays((int)firstOfLastMonth.DayOfWeek);
// Add in the DayOfWeek number we are looking for
DateTime firstFridayOfMonth = justBeforeMonth.AddDays(DayOfWeek.Friday);
// if we are still in last month, add a week to get into this month
if (firstFridayOfMonth.Month != date.AddMonth(-1).Month) { firstFridayOfMonth.AddDays(7); }
// add in 2 weeks to get the third week of the month
DateTime thirdFridayOfMonth = firstFridayOfMonth.AddDays(14);
Here's the solution I came up with. If the day doesn't exist (e.g. 8th Saturday), GetDate() will return null:
{
DateTime lastMonth = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1).AddMonths(-1);
DateTime? date = GetDate(lastMonth.Month, lastMonth.Year, DayOfWeek.Thursday, 2);
}
private static DateTime? GetDate(int month, int year, DayOfWeek dayOfWeek, int which)
{
DateTime firstOfMonth = new DateTime(year, month, 1);
DateTime date;
for (date = firstOfMonth; date.DayOfWeek != dayOfWeek; date = date.AddDays(1))
;
date = date.AddDays(7 * (which - 1));
return date.Month == month && date.Year == year ? (DateTime?)date : null;
}
I need to get a list of weeks for a given month, with Monday as the start day.
So for example, for the month of February 2009, this method would return:
2/2/2009
2/9/2009
2/16/2009
2/23/2009
// Get the weeks in a month
DateTime date = DateTime.Today;
// first generate all dates in the month of 'date'
var dates = Enumerable.Range(1, DateTime.DaysInMonth(date.Year, date.Month)).Select(n => new DateTime(date.Year, date.Month, n));
// then filter the only the start of weeks
var weekends = from d in dates
where d.DayOfWeek == DayOfWeek.Monday
select d;
public static List<DateTime> GetWeeks(
this DateTime month, DayOfWeek startOfWeek)
{
var firstOfMonth = new DateTime(month.Year, month.Month, 1);
var daysToAdd = ((Int32)startOfWeek - (Int32)month.DayOfWeek) % 7;
var firstStartOfWeek = firstOfMonth.AddDays(daysToAdd);
var current = firstStartOfWeek;
var weeks = new List<DateTime>();
while (current.Month == month.Month)
{
weeks.Add(current);
current = current.AddDays(7);
}
return weeks;
}
Here's a solution (effectively one line) using C# 3.0/LINQ, in case you're interested:
var month = new DateTime(2009, 2, 1);
var weeks = Enumerable.Range(0, 4).Select(n => month.AddDays(n * 7 - (int)month.DayOfWeek + 1)).TakeWhile(monday => monday.Month == month.Month);
int year = 2009;
int month = 2;
DateTime startDate = new DateTime(year, month, 1);
DateTime endDate = startDate.AddMonths(1);
while (startDate.DayOfWeek != DayOfWeek.Monday)
startDate = startDate.AddDays(1);
for (DateTime result = startDate; result < endDate; result = result.AddDays(7))
DoWhatYouWant(result);
How about this?
public IEnumerable<DateTime> GetWeeks(DateTime date, DayOfWeek startDay)
{
var list = new List<DateTime>();
DateTime first = new DateTime(date.Year, date.Month, 1);
for (var i = first; i < first.AddMonths(1); i = i.AddDays(1))
{
if (i.DayOfWeek == startDay)
list.Add(i);
}
return list;
}
Something like the following pseudo-code should work:
Determine the start date of the month (use month and year from a date and set the day to 1
Determine the end date of the month (start date + 1 month)
Determine the first date that is a monday (this is your first item in the list)
Add 7 days to find the next date and repeat until you read or pass the month end
Just change the response line to what ever you need to do with it
protected void PrintDay(int year, int month, DayOfWeek dayName)
{
CultureInfo ci = new CultureInfo("en-US");
for (int i = 1 ; i <= ci.Calendar.GetDaysInMonth (year, month); i++)
{
if (new DateTime (year, month, i).DayOfWeek == dayName)
Response.Write (i.ToString() + "<br/>");
}
}
Quick solution: i don't think there is a built in function for it....
I see you got your answer, but I wanted to share with you a helper class I created for one of my projects. It's far to be a comprehansive class, but might help...
public static class WeekHelper {
#region Public Methods
public static DateTime GetWeekStart(DateTime date) {
DateTime weekStart;
int monday = 1;
int crtDay = (int)date.DayOfWeek;
if (date.DayOfWeek == DayOfWeek.Sunday)
crtDay = 7;
int difference = crtDay - monday;
weekStart = date.AddDays(-difference);
return weekStart;
}
public static DateTime GetWeekStop(DateTime date) {
DateTime weekStart;
int sunday = 7;
int crtDay = (int)date.DayOfWeek;
if (date.DayOfWeek == DayOfWeek.Sunday)
crtDay = 7;
int difference = sunday - crtDay;
weekStart = date.AddDays(difference);
return weekStart;
}
public static void GetWeekInterval(int year, int weekNo,
out DateTime weekStart, out DateTime weekStop) {
GetFirstWeekOfYear(year, out weekStart, out weekStop);
if (weekNo == 1)
return;
weekNo--;
int daysToAdd = weekNo * 7;
DateTime dt = weekStart.AddDays(daysToAdd);
GetWeekInterval(dt, out weekStart, out weekStop);
}
public static List<KeyValuePair<DateTime, DateTime>> GetWeekSeries(DateTime toDate) {
//gets week series from beginning of the year
DateTime dtStartYear = new DateTime(toDate.Year, 1, 1);
List<KeyValuePair<DateTime, DateTime>> list = GetWeekSeries(dtStartYear, toDate);
if (list.Count > 0) {
KeyValuePair<DateTime, DateTime> week = list[0];
list[0] = new KeyValuePair<DateTime, DateTime>(dtStartYear, week.Value);
}
return list;
}
public static List<KeyValuePair<DateTime, DateTime>> GetWeekSeries(DateTime fromDate, DateTime toDate) {
if (fromDate > toDate)
return null;
List<KeyValuePair<DateTime, DateTime>> list = new List<KeyValuePair<DateTime, DateTime>>(100);
DateTime weekStart, weekStop;
toDate = GetWeekStop(toDate);
while (fromDate <= toDate) {
GetWeekInterval(fromDate, out weekStart, out weekStop);
list.Add(new KeyValuePair<DateTime, DateTime>(weekStart, weekStop));
fromDate = fromDate.AddDays(7);
}
return list;
}
public static void GetFirstWeekOfYear(int year, out DateTime weekStart, out DateTime weekStop) {
DateTime date = new DateTime(year, 1, 1);
GetWeekInterval(date, out weekStart, out weekStop);
}
public static void GetWeekInterval(DateTime date,
out DateTime dtWeekStart, out DateTime dtWeekStop) {
dtWeekStart = GetWeekStart(date);
dtWeekStop = GetWeekStop(date);
}
#endregion Public Methods
}
This works beautifully! All you have to do is get the first day of the month you want to get the weeks for and then this will give you the first day of every week. You need to get 5 weeks (not 4) so the Enumerable.Range counts out 5 instead of 4.
var date = new DateTime(DateTime.Today.Year, DateTime.Today.Month, 1);
var weeks = from n in Enumerable.Range(0, 5)
select date.AddDays(7 * n + (-1 * (int)date.DayOfWeek));
Here's what i did, using Chaowlert's code as a starting base. Basically i modified that you need to check if adding the days in the for overflows to the next month, so i don't add 4 days (monday to friday), but actually the minimum between 4 and the number of remaining days in the month. Also, i check if the current day is a weekend, otherwise add days until it's a weekday. My purpose is to print the weeks in a month, from monday to friday
DateTime fechaInicio = new DateTime(año, mes, 1);
DateTime fechaFin = fechaInicio.AddMonths(1);
int diasHastaFinMes = 0;
while (esFinDeSemana(fechaInicio))
fechaInicio = fechaInicio.AddDays(1);
for (DateTime fecha = fechaInicio; fecha < fechaFin; fecha = fecha.AddDays(7))
{
diasHastaFinMes = DateTime.DaysInMonth(fecha.Year, fecha.Month) - fecha.Day;
printWeeks(fecha, fecha.AddDays(Math.Min(4, diasHastaFinMes)));
}