Select 两个日期之间的月份

Select months between two dates

我正在尝试创建一个表格,该表格将从数据库中获取考勤数据并传输到 excel sheet 以打印出来。

我已经创建了表格,并且通过两个日期时间选择器,我设法获得了开始旅行报销的月份以及我也想报销的月份。

我正在努力将其分成单独的月份,以便我可以使用单独的月份来整合数据库。

到目前为止我有

    if (TodateTimePicker.Value.Date <= FromdateTimePicker.Value.Date)
    {
        MessageBox.Show("End Date must be after Start Date");
    }
    else
    {
        fromDate = FromdateTimePicker.Value.Date;
        toDate = TodateTimePicker.Value.Date;

        fromDate = (fromDate.AddDays(1 - fromDate.Day));

        toDate = (toDate.AddDays(1 - toDate.Day)).AddMonths(1).AddDays(-1)
    }

我还有要使用的数据库命令

            com = new OleDbCommand("SELECT count(*), FROM Attendances WHERE year([Attendance_Date]) = ? GROUP BY [Person] ORDER BY count(*) DESC", Program.DB_CONNECTION);
            com.Parameters.Add(new OleDbParameter("", month));
            com.Parameters.Add(new OleDbParameter("", p.ID));

我真正的问题是如何获取所选两个日期之间的每个月的第一天和每个月的最后一天?

这是我发现的两种最简单的方法:

private int IntervalInMonthsBetweenDates(DateTime date1, DateTime date2)
{
    return date2.Subtract(date1).Days / 30;
}


private int IntervalInMonthsBetweenDates(DateTime date1, DateTime date2)
{
    return ((date1.Year - date2.Year) * 12) + date1.Month - date2.Month;
}
for (DateTime i = fromDate; i.Date <= toDate.Date; i = i.AddMonths(1))
        {
            Console.WriteLine(i.Month);
        }

如果您想要在给定 DateTimes 的两个年份和月份之间的 DateTime 序列,其中表示月份的每个开始和结束,那么您可以执行以下操作。

public static IEnumerable<DateTime> BeginEndOfEachMonthBetween(DateTime from, DateTime to)
{
    DateTime start = from.AddDays(1 - from.Day);
    while(start <= to)
    {
        yield return start;
        yield return start.AddMonths(1).AddDays(-1);
        start.AddMonths(1);
    }
}

但是看看你打算如何使用它会有所帮助。

听起来您可能需要类似于此的查询

SELECT 
    DatePart(year,Attendance_Date) As Year, 
    DatePart(month,Attendance_Date) As Month, 
    Count(*) As Attendance
FROM Attendances 
WHERE Attendance_Date Between @BeginDate And @EndDate
GROUP BY 
    DatePart(year,Attendance_Date), 
    DatePart(month,Attendance_Date) 

我想出了一个解决方案,我计算了两个日期之间的月数,然后 运行 通过循环将月数添加到开始日期,得到第一天和最后一天两个原始日期之间的每个月,可能不是最巧妙的方式,但它完全按照我的计划工作。

int 个月 = ((toDate.Year - fromDate.Year) * 12 + toDate.Month - fromDate.Month) + 1; // 求出两个日期之间的月数并加一

        DateTime dateofclaim = new DateTime(); // define dateofclame to a new date  

        for (int i = 0; i < months; i++) // for each month run the code below, this will first run the fromDate then add a month until it gets to the toDate
        {
            dateofclaim = fromDate.AddMonths(i); // add one month to the start date

            claimfromDate = (dateofclaim.AddDays(1 - dateofclaim.Day)); // calculate the first date of the month

            claimtoDate = (dateofclaim.AddDays(1 - dateofclaim.Day)).AddMonths(1).AddDays(-1); // calculate the last day of the month

            OleDbCommand com = new OleDbCommand("SELECT sum([sum]) FROM Attendance WHERE ([Attendance_Date]) >= ? AND ([Attendance_Date]) <= ? AND [Person] = ?", Program.DB_CONNECTION); // count the total attendances in the month
            com.Parameters.Add(new OleDbParameter("", claimfromDate));
            com.Parameters.Add(new OleDbParameter("", claimtoDate));
            com.Parameters.Add(new OleDbParameter("", person.ID));

            OleDbDataReader dr = com.ExecuteReader(); // start reader  

            if (dr.Read()) // if a result is returned
            {
                try
                {
                    int attendance = Convert.ToInt32(dr.GetDouble(0)); // this is how many attendances have been counted for the selected month

                    ws.get_Range("B" + row.ToString()).Value2 = dateofclaim.ToString("MMM yyyy"); // print the Month of the clame into Colum B and row 83 then adding one for each following month
                    ws.get_Range("I" + row.ToString()).Value2 = attendance.ToString(); // print the number of attendances into Colum B and the respective row
                    row++; // add one to the row so next time this runs the data will be on the next row 
                }
                catch // if nothing as returned from the database then add the month and 0 in the attendance colum
                {
                    ws.get_Range("B" + row.ToString()).Value2 = dateofclaim.ToString("MMM yyyy");
                    ws.get_Range("I" + row.ToString()).Value2 = "0";
                    row++;
                }
            }
            dr.Close(); // close the database reader
        }