C# 查找日历的第一天

C# 查找日历的第一天,c#,datetime,calendar,C#,Datetime,Calendar,我想做的是创建一个简单的日历,我想找到特定月份第一周的第一天。我的日历是星期一->星期天日历,下面的代码可以工作,但正如您所看到的,它并没有那么好。对于如何在日历中获得第一个日期,任何人都有更好的想法 var now = new DateTime(Year, Month, 1); now = now.AddDays(1-(int)now.DayOfWeek); now = now.Day > 15 ? now : now.AddDays(-7); 日历将以如下方式结束: | <

我想做的是创建一个简单的日历,我想找到特定月份第一周的第一天。我的日历是星期一->星期天日历,下面的代码可以工作,但正如您所看到的,它并没有那么好。对于如何在日历中获得第一个日期,任何人都有更好的想法

var now = new DateTime(Year, Month, 1);
now = now.AddDays(1-(int)now.DayOfWeek);
now = now.Day > 15 ? now : now.AddDays(-7);
日历将以如下方式结束:

| <  |        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 |
var firstCalDate = DateTime.Now.FirstDateOfCalendarMonth(DayOfWeek.Monday);
/溴
Andreas

您可以使用模来计算无条件语句的填充天数:

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

我会这么做的。这很容易理解:

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;
}

此外,如果您想将日历更改为从星期一以外的时间开始,那么现在就很简单了。使用模运算的解决方案将无法维护

假设你指的第一天是星期一,你可以试试这个

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

更新:下面的代码有一个bug!使用模运算,以补偿环境,.NET在星期天开始一周!请参阅此处的其他解决方案(不包括具有额外功能的解决方案)

如果您需要查找“27”(即显示一个月的第一天),只需使用以下命令:

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

我不喜欢while循环,因为它们与LINQ一起使用时非常昂贵
希望其他人可以重用此代码:(如果您在美国,则只需删除两行中的[+6)%7])

//
///扩展月份。
///|<| 2011年1月|>|
/// ------------------------------------
///|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 |
/// 
///在感兴趣月份的某一天,开始日期将更新为第一天日历的日期
///要显示的天数。该值为(28、35或42)
公共静态月(参考日期时间开始)
{
DateTime first=新的日期时间(start.Year,start.Month,1);
DateTime last=新的日期时间(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);
最后返回。减去(开始)。天;
}

//Thomas

我发现自己经常需要这样做,所以我创建了以下扩展方法

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;
}
像这样使用它

var firstCalDate = DateTime.Now.FirstDateOfCalendarMonth();
它默认为星期天为星期一,但您可以通过任何您喜欢的星期天,如下所示:

| <  |        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 |
var firstCalDate = DateTime.Now.FirstDateOfCalendarMonth(DayOfWeek.Monday);
DateTime start\u date=Cal\u start\u date.SelectedDate;
DateTime end\u date=Cal\u end\u date.SelectedDate;
字典dic_week_day=新字典();
星期日[“星期日”]=1;
星期一[“星期一”]=2;
星期一[“星期二”]=3;
星期三=4天;
星期四=5天;
星期五=6天;
星期六=7天;
DateTime first\u day=开始日期.AddDays(1-开始日期.day);
int selected_day=dic_week_day[Drp_day_of u week.SelectedValue.ToString();
字符串str_html=“”;
for(DateTime i=第一天;我选择了第一天)
{
临时日期=i.AddDays((每周7天)+所选日期);
}
其他的
{
临时日期=i.AddDays(所选的日期-每周的日期);
}
DateTime last_day_of_month=(临时日期AddMonths(1)).AddDays(-临时日期.day);
if(Drp_occurrence.SelectedValue.ToString()=“奇数”)
{

如果(开始日期,但为什么?它不是很容易理解的。有更清晰的代码可以立即掌握。当你需要维护某个东西时,你会很感激在三个月内编写它,或者老天保佑,修复其中一个讨厌的错误,因为它太不清楚了。为什么这么复杂?更简单的解决方案exist@user492238依我看,这个代码很简单比你的(和我的)解决方案。循环在最多7次迭代后终止,因此性能也很好。我不是反对者,但我怀疑您的代码在一个可能的工作日内不起作用,因为.net将星期日视为一周的第一天,而OP Monday视为一周的第一天。此代码有一个bug,它的含义不是很明显,并且不可维护。@Jason你说的“可维护”是什么意思?为什么这在任何方面都是“可维护的”呢?一般来说,为将来可能出现的每一个可能的更改请求做准备都不是一个好的编码实践。所以像这样的代码应该简单有效,而不是单独使用。@user492238:但这不是“可维护的”的意思。“可维护的”这并不意味着为每一个可能的变更请求做好准备。相反,这意味着编码方式要易于纠正缺陷并满足未来需求。这并不意味着试图预测未来的请求并对其编码,而是要以一种更容易满足未来请求的方式编码。可维护代码的一个特点是可读性。更容易理解的代码更容易维护。+1#哇,实际上我在大学时用C在控制台应用程序中制作了一个类似的日历。很好。我不知道可以将DayOfWeek转换为int。我总是看到它显示day字符串:“周一”.@DougS这是一个枚举,您可以将任何枚举强制转换为基础整数类型。@CodesInChaos:很高兴知道。谢谢!
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;