C# 获取C中两个日期之间的日历周数#

C# 获取C中两个日期之间的日历周数#,c#,asp.net,C#,Asp.net,出于这个问题的目的,我们假设用户来自美国,使用标准的公历。因此,日历周从周日开始,到周六结束 我想做的是确定两个日期之间存在的日历周数。我的问题的一个完美例子是在2010年10月。在2016年10月至31日之间,有4个日历周 10月10日至10月16日 10月17日至10月23日 10月24日至10月30日 10月31日至11月6日 我宁愿远离任何硬编码逻辑,如: if (Day == DayOfWeek.Saturday && LastDayOfMonth == 31) {

出于这个问题的目的,我们假设用户来自美国,使用标准的公历。因此,日历周从周日开始,到周六结束

我想做的是确定两个日期之间存在的日历周数。我的问题的一个完美例子是在2010年10月。在2016年10月至31日之间,有4个日历周


  • 10月10日至10月16日
  • 10月17日至10月23日
  • 10月24日至10月30日
  • 10月31日至11月6日

  • 我宁愿远离任何硬编码逻辑,如:

    if (Day == DayOfWeek.Saturday && LastDayOfMonth == 31) { ... }
    
    有人能想出一个合乎逻辑的方法来做这件事吗?

    更新:
    感谢大家的积极回应,经过深思熟虑,以下是我使用的解决方案:

    //get the start and end dates of the current pay period
    DateTime currentPeriodStart = SelectedPeriod.Model.PeriodStart;
    DateTime currentPeriodEnd = SelectedPeriod.Model.PeriodEnd;
    
    //get the first sunday & last saturday span that encapsulates the current pay period
    DateTime firstSunday = DayExtensions.SundayBeforePeriodStart(currentPeriodStart);
    DateTime lastSaturday = DayExtensions.SaturdayAfterPeriodEnd(currentPeriodEnd);
    
    //get the number of calendar weeks in the span
    int numberOfCalendarWeeks = DayExtensions.CalendarWeeks(firstSunday, lastSaturday);
    
    以下是helper类中的方法:

        /// <summary>
        /// Get the first Sunday before the pay period start date
        /// </summary>
        /// <param name="periodStartDate">Date of the pay period start date</param>
        /// <returns></returns>
        public static DateTime SundayBeforePeriodStart(DateTime periodStartDate)
        {
            DateTime firstDayOfWeekBeforeStartDate;
    
            int daysBetweenStartDateAndPreviousFirstDayOfWeek = (int)periodStartDate.DayOfWeek - (int)DayOfWeek.Sunday;
    
            if (daysBetweenStartDateAndPreviousFirstDayOfWeek >= 0)
            {
                firstDayOfWeekBeforeStartDate = periodStartDate.AddDays(-daysBetweenStartDateAndPreviousFirstDayOfWeek);
            }
            else
            {
                firstDayOfWeekBeforeStartDate = periodStartDate.AddDays(-(daysBetweenStartDateAndPreviousFirstDayOfWeek + 7));
            }
    
            return firstDayOfWeekBeforeStartDate;
        }
    
        /// <summary>
        /// Get the first Saturday after the period end date
        /// </summary>
        /// <param name="periodEndDate">Date of the pay period end date</param>
        /// <returns></returns>
        public static DateTime SaturdayAfterPeriodEnd(DateTime periodEndDate)
        {
            DateTime lastDayOfWeekAfterEndDate;
    
            int daysBetweenEndDateAndFollowingLastDayOfWeek = (int)DayOfWeek.Saturday - (int)periodEndDate.DayOfWeek;
    
            if (daysBetweenEndDateAndFollowingLastDayOfWeek >= 0)
            {
                lastDayOfWeekAfterEndDate = periodEndDate.AddDays(daysBetweenEndDateAndFollowingLastDayOfWeek);
            }
            else
            {
                lastDayOfWeekAfterEndDate = periodEndDate.AddDays(daysBetweenEndDateAndFollowingLastDayOfWeek + 7);
            }
    
            return lastDayOfWeekAfterEndDate;
        }
    
        /// <summary>
        /// Get the calendar weeks between 2 dates
        /// </summary>
        /// <param name="d1">First day of date span</param>
        /// <param name="d2">Last day of date span</param>
        /// <returns></returns>
        public static int CalendarWeeks(DateTime d1, DateTime d2)
        {
            return 1 + (int)((d2 - d1).TotalDays / 7);
        }
    
    //
    ///在付款期开始日期前的第一个星期日
    /// 
    ///支付期开始日期的日期
    /// 
    公共静态DateTime SundayBeforiodStart(DateTime periodStartDate)
    {
    DateTime firstDayOfWeekBeforeStartDate;
    StartDate和上一个FirstDayOfWeek之间的整数天=(int)时段StartDate.DayOfWeek-(int)DayOfWeek.Sunday;
    if(开始日期和上一周第一天之间的天数>=0)
    {
    FirstDayOfWeekBeforestDate=时段StartDate.AddDays(-StartDate和上一周第一天之间的天数);
    }
    其他的
    {
    FirstDayOfWeekBeforRestartDate=时段StartDate.AddDays(-(StartDate和上一周FirstDayOfWeek+7之间的天数));
    }
    返回WeekBeforestartDate的第一天;
    }
    /// 
    ///获取时段结束日期后的第一个星期六
    /// 
    ///支付期结束日期的日期
    /// 
    公共静态日期时间SaturdayAfterPeriodEnd(日期时间periodEndDate)
    {
    DateTime lastDayOfWeekAfterEndDate;
    EndDate和LastDayOfWeek之间的整数天=(int)DayOfWeek.Saturday-(int)periodEndDate.DayOfWeek;
    如果(EndDate和LastDayOfWeek>=0之间的天数)
    {
    lastDayOfWeekAfterEndDate=periodEndDate.AddDays(介于EndDate和LastDayOfWeek之后的日期);
    }
    其他的
    {
    lastDayOfWeekAfterEndDate=periodEndDate.AddDays(EndDate和LastDayOfWeek+7之间的天数);
    }
    返回lastDayOfWeekAfterEndDate;
    }
    /// 
    ///获取两个日期之间的日历周
    /// 
    ///日期跨度的第一天
    ///日期跨度的最后一天
    /// 
    公共静态整数日历周(日期时间d1、日期时间d2)
    {
    返回1+(整数)((d2-d1)。总天数/7);
    }
    
    如果你好奇的话,这就是我最后对约会所做的:

    //create an array of all the sundays in this span
    DateTime[] _sundays = new DateTime[numberOfCalendarWeeks];
    
    //put the first sunday in the period
    _sundays[0] = firstSunday;
    
    //step through each week and get each sunday until you reach the last saturday
    for (int i = 1; i <= numberOfCalendarWeeks - 1; i++)
    {
         DateTime d = new DateTime();
         d = firstSunday.AddDays(i * 7);
          _sundays[i] = d;
    }
    
    for (int i = 0; i <= _sundays.Length-1; i++)
    {
          //bind my view model with each sunday.
    }
    
    //创建此范围内所有星期日的数组
    DateTime[]_sundays=新日期时间[日历周数];
    //把第一个星期天放在这段时间里
    _星期日[0]=第一个星期日;
    //每周一次,每周日一次,直到你到达最后一个周六
    对于(int i=1;i
    没有比这更好的办法了

    private static int weekDifference(DateTime startDate, DateTime endDate)
    {
         const int firstDayOfWeek = 0;  // Sunday
         int wasteDaysStart = (7+startDate.DatOfWeek-firstDayOfWeek)%7;
         return (int)(((endDate-startDate).TotalDays() + wasteDaysStart + 6)/7);
    }
    

    警告:未测试的代码。请测试并删除注释。

    请记住,在不同的区域性中,周计算是不同的,如果您看到第53周,则不会出现错误

    using System.Globalization;
    
    CultureInfo cultInfo = CultureInfo.CurrentCulture;
    int weekNumNow = cultInfo.Calendar.GetWeekOfYear(DateTime.Now,
                         cultInfo.DateTimeFormat.CalendarWeekRule,
                             cultInfo.DateTimeFormat.FirstDayOfWeek); 
    

    这里有一个通用的解决方案,我相信它适用于任何一周的开始和结束日期。您可以根据自己的情况简化它,但此代码为您提供了更改一周开始和结束日期的选项(例如,从周一到周日)在工资单应用程序中,更改日历周的定义并不少见

            DateTime periodStart = new DateTime(2010, 10, 17);
            DateTime periodEnd = new DateTime(2010, 11, 14);
    
            const DayOfWeek FIRST_DAY_OF_WEEK = DayOfWeek.Monday;
            const DayOfWeek LAST_DAY_OF_WEEK = DayOfWeek.Sunday;
            const int DAYS_IN_WEEK = 7;
    
            DateTime firstDayOfWeekBeforeStartDate;
            int daysBetweenStartDateAndPreviousFirstDayOfWeek = (int)periodStart.DayOfWeek - (int)FIRST_DAY_OF_WEEK;
            if (daysBetweenStartDateAndPreviousFirstDayOfWeek >= 0)
            {
                firstDayOfWeekBeforeStartDate = periodStart.AddDays(-daysBetweenStartDateAndPreviousFirstDayOfWeek);
            }
            else
            {
                firstDayOfWeekBeforeStartDate = periodStart.AddDays(-(daysBetweenStartDateAndPreviousFirstDayOfWeek + DAYS_IN_WEEK));
            }
    
            DateTime lastDayOfWeekAfterEndDate;
            int daysBetweenEndDateAndFollowingLastDayOfWeek = (int)LAST_DAY_OF_WEEK - (int)periodEnd.DayOfWeek;
            if (daysBetweenEndDateAndFollowingLastDayOfWeek >= 0)
            {
                lastDayOfWeekAfterEndDate = periodEnd.AddDays(daysBetweenEndDateAndFollowingLastDayOfWeek);
            }
            else
            {
                lastDayOfWeekAfterEndDate = periodEnd.AddDays(daysBetweenEndDateAndFollowingLastDayOfWeek + DAYS_IN_WEEK);
            }
    
            int calendarWeeks = 1 + (int)((lastDayOfWeekAfterEndDate - firstDayOfWeekBeforeStartDate).TotalDays / DAYS_IN_WEEK);
    

    我解决这个问题的方法是为任何给定的日期计算一周的开始。使用这个方法,你可以从结束日期的结果中减去开始日期的结果。然后你的日差总是7的倍数,所以除以并加1(0天=>1周,7天=>2周,等等)。这将告诉您任意两个日期涵盖或代表了多少个日历周

    static int GetWeeksCovered(DateTime startDate, DateTime endDate)
    {
        if (endDate < startDate)
            throw new ArgumentException("endDate cannot be less than startDate");
    
        return (GetBeginningOfWeek(endDate).Subtract(GetBeginningOfWeek(startDate)).Days / 7) + 1;
    }
    
    static DateTime GetBeginningOfWeek(DateTime date)
    {
        return date.AddDays(-1 * (int)date.DayOfWeek).Date;
    }
    
    static int GetWeeksCovered(DateTime startDate,DateTime endDate)
    {
    如果(结束日期<开始日期)
    抛出新ArgumentException(“endDate不能小于startDate”);
    返回(GetBeginingOffweek(endDate)。减去(GetBeginingOffweek(startDate))。天/7)+1;
    }
    静态日期时间GetBeginingOfWeek(日期时间日期)
    {
    返回日期.AddDays(-1*(int)date.DayOfWeek)。日期;
    }
    
    • 2010年10月16日和2010年10月16日=>涵盖(或代表)1周
    • 根据规范,2010年10月16日和2010年10月31日=>涵盖4周

    以下内容似乎适用于任何日期范围。它应该是文化上合理的,并且应该考虑闰年/闰日或其他日历上的奇怪现象:

        private static int getWeeksSpannedBy(DateTime first, DateTime last)
        {
            var calendar = CultureInfo.CurrentCulture.Calendar;
            var weekRule = CultureInfo.CurrentCulture.DateTimeFormat.CalendarWeekRule;
            var firstDayOfWeek = DayOfWeek.Sunday;
    
            int lastWeek = calendar.GetWeekOfYear(last, weekRule, firstDayOfWeek);
            int firstWeek = calendar.GetWeekOfYear(first, weekRule, firstDayOfWeek);
    
            int weekDiff = lastWeek - firstWeek + 1;
    
            return weekDiff;
        }
    
        static void Main(string[] args)
        {
            int weeks1 = getWeeksSpannedBy(new DateTime(2010, 1, 3), new DateTime(2010, 1, 9));
            int weeks2 = getWeeksSpannedBy(new DateTime(2010, 10, 16), new DateTime(2010, 10, 31));
            int weeks3 = getWeeksSpannedBy(new DateTime(2008, 2, 1), new DateTime(2008, 2, 29));
            int weeks4 = getWeeksSpannedBy(new DateTime(2012, 2, 1), new DateTime(2012, 2, 29));
    
            Console.WriteLine("Weeks Difference #1: " + weeks1);
            Console.WriteLine("Weeks Difference #2: " + weeks2);
            Console.WriteLine("Weeks Difference #3: " + weeks3);
            Console.WriteLine("Weeks Difference #4: " + weeks4);
            Console.ReadLine();
        }
    
    打印以下内容,这些内容适用于所有日期范围,包括过去、现在或将来(闰年2008年和2012年2月1日和2月29日之间都有5周):

    周差#1:1
    周差#2:4
    周差#3:5

    周差4:5

    星期六是一周的最后一天,是吗

    public int CalendarWeeks(DateTime from, DateTime to) {
    
        // number of multiples of 7 
        // (rounded up, since 15 days would span at least 3 weeks)
        // and if we end on a day before we start, we know it's another week
    
        return (int)Math.Ceiling(to.Subtract(from).Days / 7.0) + 
                (to.DayOfWeek <= from.DayOfWeek) ? 1 : 0;
    }
    
    public int CalendarWeeks(日期时间从,日期时间到){
    //7的倍数
    //(四舍五入,因为15天将至少持续3周)
    //如果我们在开始前一天结束,我们知道又是一周
    返回(整数)数学上限(到.减去.Days/7.0)+
    
    (to.DayOfWeek如果我理解正确,您需要两个给定日期之间的完整周数(我认为应该是从周一到周日),因此从6月18日星期四到6月24日星期三,您不会有一周(如7天),但没有,因为您只经过一次星期一,之后不会到达星期天,对吗?此特定应用程序需要Sun-Sat。请考虑一个月内的两个发薪期(10/1期和10/16期)。此场景中的一个工作周是Sun-Sat。因此,10/16发薪期贯穿4个日历周。
    public int CalendarWeeks(DateTime from, DateTime to) {
    
        // number of multiples of 7 
        // (rounded up, since 15 days would span at least 3 weeks)
        // and if we end on a day before we start, we know it's another week
    
        return (int)Math.Ceiling(to.Subtract(from).Days / 7.0) + 
                (to.DayOfWeek <= from.DayOfWeek) ? 1 : 0;
    }