Andreas
Andreas

Reputation: 7248

Finding first day of calendar

What i want to do is to create a simple calendar, and I want to find the first day of the first week of a specific month. My calendar is a Monday -> Sunday calendar and the following code works, but as you can see it's not that nice. Anyone have any better idea on how to get the first date in the calendar.

var now = new DateTime(Year, Month, 1);
now = now.AddDays(1-(int)now.DayOfWeek);
now = now.Day > 15 ? now : now.AddDays(-7);

The calendar will end up looking like this:

| <  |        Jan  2011       |  > |
------------------------------------
| Mo | Tu | We | Th | Fr | Sa | Su |
|[27]| 28 | 29 | 30 | 31 | 01 | 02 |
| 03 | 04 | 05 | 06 | 07 | 08 | 09 |
| .. | .. | .. | .. | .. | .. | .. |
| .. | .. | .. | .. | .. | .. | .. |
| 31 | 01 | 02 | 03 | 04 | 05 | 06 |

And in this "image" it's the [27] date that i'm trying to find.

Solution (Found i better/cleaner to loop then calculate):

    public DateTime FirstDay()
    {
        var date = new DateTime(Date.Year, Date.Month, 1);
        while (true)
        {
            if (date.DayOfWeek == DayOfWeek.Monday)
                return date;
            date = date.AddDays(-1);
        }
        return date;
    }

    public DateTime LastDay()
    {
        var date = new DateTime(Date.Year, Date.Month, 
                                DateTime.DaysInMonth(Date.Year, Date.Month));
        while (true)
        {
            if (date.DayOfWeek == DayOfWeek.Sunday)
                return date;
            date = date.AddDays(1);
        }
        return date;
    }

/BR Andreas

Upvotes: 14

Views: 6426

Answers (7)

user3448924
user3448924

Reputation: 11

DateTime start_date = Cal_start_date.SelectedDate;
DateTime end_date = Cal_end_date.SelectedDate;

Dictionary<string, int> dic_week_day = new Dictionary<string, int>();
dic_week_day["Sunday"] = 1;
dic_week_day["Monday"] = 2;
dic_week_day["Tuesday"] = 3;
dic_week_day["Wednesday"] = 4;
dic_week_day["Thursday"] = 5;
dic_week_day["Friday"] = 6;
dic_week_day["Saturday"] = 7;

DateTime first_day = start_date.AddDays(1 - start_date.Day);
int selected_day = dic_week_day[Drp_day_of_week.SelectedValue.ToString()];

string str_html = "";
for (DateTime i = first_day; i <= end_date; i = i.AddMonths(1))
{
    int day_of_week = dic_week_day[i.DayOfWeek.ToString()];
    DateTime temp_date;
    if (day_of_week > selected_day)
    {
        temp_date = i.AddDays((7 - day_of_week) + selected_day);
    }
    else
    {
        temp_date = i.AddDays(selected_day - day_of_week);
    }

    DateTime last_day_of_month = (temp_date.AddMonths(1)).AddDays(-temp_date.Day);

    if (Drp_occurrence.SelectedValue.ToString() == "odd")
    {
        if (start_date <= temp_date && temp_date <= end_date && temp_date <= last_day_of_month)
        {
            str_html += "<br />" + temp_date.ToString();
        }

        DateTime res_date = temp_date.AddDays(14);

        if (start_date <= res_date && res_date <= end_date && res_date <= last_day_of_month)
        {
            str_html += "  ,  " + res_date.ToString();
        }

        res_date = temp_date.AddDays(28);

        if (start_date <= res_date && res_date <= end_date && res_date <= last_day_of_month)
        {
            str_html += "  ,  " + res_date.ToString();
        }
    }
    else if (Drp_occurrence.SelectedValue.ToString() == "even")
    {
        DateTime res_date = temp_date.AddDays(7);

        if (start_date <= res_date && res_date <= end_date && res_date <= last_day_of_month)
        {
            str_html += "<br />" + res_date.ToString();
        }

        res_date = temp_date.AddDays(21);

        if (start_date <= res_date && res_date <= end_date && res_date <= last_day_of_month)
        {
            str_html += "  ,  " + res_date.ToString();
        }
    }
    else
    {
        int occurrence = Int32.Parse(Drp_occurrence.SelectedValue.ToString());

        DateTime res_date = temp_date.AddDays((occurrence - 1) * 7);

        if (start_date <= res_date && res_date <= end_date && res_date <= last_day_of_month)
        {
            str_html += "<br />" + res_date.ToString();
        }
    }
}

Div_result.InnerHtml = str_html;

Upvotes: 0

Brad Bamford
Brad Bamford

Reputation: 3873

I found myself needing to do this quite often, so I created the following extension method.

public static DateTime FirstDateOfCalendarMonth(this DateTime dt, DayOfWeek firstDayOfWeek = DayOfWeek.Sunday)
{
  dt = new DateTime(dt.Year, dt.Month, 1);
  while (dt.DayOfWeek != firstDayOfWeek){
    dt = dt.AddDays(-1);
  }
  return dt;
}

Use it like this

var firstCalDate = DateTime.Now.FirstDateOfCalendarMonth();

It defaults to Sunday as the first DayOfWeek, but you can pass it whatever DayOfWeek you like, like this:

var firstCalDate = DateTime.Now.FirstDateOfCalendarMonth(DayOfWeek.Monday);

Upvotes: 0

thomas nn
thomas nn

Reputation: 943

I do not like while loops, because they are expensive when used with LINQ
Hope someone else can reuse this code: (if you are in the USA, then just remove [ + 6) % 7)] in two lines)

    /// <summary>
    /// Expands the month.
    /// | <  |        Jan  2011       |  > |
    /// ------------------------------------
    /// | Mo | Tu | We | Th | Fr | Sa | Su |
    /// |[27]| 28 | 29 | 30 | 31 | 01 | 02 |
    /// | 03 | 04 | 05 | 06 | 07 | 08 | 09 |
    /// | .. | .. | .. | .. | .. | .. | .. |
    /// | .. | .. | .. | .. | .. | .. | .. |
    /// | 31 | 01 | 02 | 03 | 04 | 05 | 06 |
    /// </summary>
    /// <param name="start">Some day in the month of interest, the start date is updated to become the date of firstDayInCalendar</param>
    /// <returns>The number of days to show. This value is either (28, 35 or 42)</returns>
    public static int ExpandMonth(ref DateTime start)
    {
        DateTime first = new DateTime(start.Year, start.Month, 1);
        DateTime last = new DateTime(start.Year, start.Month, DateTime.DaysInMonth(start.Year, start.Month));
        start = first.AddDays(-((int)first.DayOfWeek + 6) % 7);
        last = last.AddDays(7 - ((int)last.DayOfWeek + 6) % 7);
        return last.Subtract(start).Days;
    }

//Thomas

Upvotes: 1

user492238
user492238

Reputation: 4084

UPDATE: Following code has a bug! Use modulo arithmetic, to compensate the circumstance, .NET begins the week on sunday! See other solutions here (without the one with an extra function).

If you need to find the "27" (i.e. the first day for the display of a month) simply use this:

DateTime monthStart = new DateTime(year, month, 1); 
DateTime monthDisplayStart = monthStart.AddDays(-((int)monthStart.DayOfWeek - 1));

Upvotes: -1

jason
jason

Reputation: 241611

I would just do this. It is so easy to understand:

var firstDayOfMonth = new DateTime(year, month, 1);
DateTime startOfCalendar = 
    FirstDayOfWeekOnOrBefore(
        firstDayOfMonth,
        DayOfWeek.Monday
    );

public static DateTime FirstDayOfWeekOnOrBefore(
    DateTime date,
    DayOfWeek dayOfWeek
) {
    while(date.DayOfWeek != dayOfWeek) {
        date = date.AddDays(-1);
    }
    return date;
}

Additionally, if you want to change your calendar to start on something other than Monday, it's trivial now. A solution using modulo arithmetic would not be as maintainable.

Upvotes: 9

CodesInChaos
CodesInChaos

Reputation: 108790

You can use modulo to calculate the number of filler days without a conditional statement:

DateTime firstOfMonth=new DateTime(year,month,1);
var weekDay=firstOfMonth.DayOfWeek;
int fillerDays=((int)weekDay+6)%7;
DateTime firstDayInCalendar=firstOfMonth.AddDays(-fillerDays);

Upvotes: 4

V4Vendetta
V4Vendetta

Reputation: 38200

You can try this assuming first day ur referring to is Monday

DateTime dt = new DateTime(2011, 2, 2);
Console.WriteLine(dt.AddDays((8 - (int)dt.DayOfWeek) % 7));

Upvotes: 1

Related Questions