【问题标题】:Week difference between 2 dates in C#C#中2个日期之间的周差
【发布时间】:2018-04-19 14:52:11
【问题描述】:

我正在尝试在 C# 中创建一个函数来返回两个日期之间的周差。它的目标是提供相同的结果:

select datediff(ww,'2018-04-13','2018-04-16') as diff

在上面的例子中,这些日期之间只有 3 天,但它们是在不同的周内,所以结果应该是 1。

我尝试使用.TotalDays,但它无法正常工作。我也试过.GetWeekOfYear,但是当日期的年份不同时它不会正确返回。我在 StackOverflow 和其他论坛上似乎有很多问题,到目前为止,没有一个问题符合我的情况。这是我正在尝试的功能:

public static int GetWeekDiff(DateTime dtStart, DateTime dtEnd) {
    // Doesn't work
    var val = ((dtEnd - dtStart).TotalDays / 7);
    val = Math.Ceiling(val);
    return Convert.ToInt32(val);

    // Doesn't work well between years
    DateTimeFormatInfo dinfo = DateTimeFormatInfo.CurrentInfo;
    var x = dinfo.Calendar.GetWeekOfYear(dtStart, CalendarWeekRule.FirstFullWeek, DayOfWeek.Monday);
    var y = dinfo.Calendar.GetWeekOfYear(dtEnd, CalendarWeekRule.FirstFullWeek, DayOfWeek.Monday);

    return y - x;

}

在函数的第一部分,我尝试了this post 中描述的内容。它没有工作

你能帮帮我吗? 提前致谢。

【问题讨论】:

  • 有什么问题,只需检查年份,如果它们不一样,则将年份的所有周加起来并添加到差异中
  • @Leustherin 部分重叠,但如果星期天到星期一(相隔 1 天),OP 希望返回 1 周,如果星期六到星期日在同一周返回 0 周。有点扭曲。
  • 您可以计算每个日期的一周开始时间,然后得到 TotalDays 并除以 7 并四舍五入。您需要确定您认为一周的开始时间以及如果第二个日期在第一个日期之前您想要返回什么等。
  • 能否提供更多测试用例和预期结果?

标签: c# datetime date-difference


【解决方案1】:

首先计算两个日期之间的天数。将天数除以 7 得到整周。

现在,通过计算天数模数 7 来计算剩余天数,确定是否还有额外的一周。如果第一个日期加上剩余天数落在不同的一周,则在计数中增加一周。

void Main()
{

    var first = new DateTime(2018, 04, 13);
    var second = new DateTime(2018, 04, 16);

    Console.WriteLine(weekDiff(first, second));
}

public int weekDiff(DateTime d1, DateTime d2, DayOfWeek startOfWeek = DayOfWeek.Monday)
{
    var diff = d2.Subtract(d1);

    var weeks = (int)diff.Days / 7;

    // need to check if there's an extra week to count
    var remainingDays = diff.Days % 7;
    var cal = CultureInfo.InvariantCulture.Calendar;
    var d1WeekNo = cal.GetWeekOfYear(d1, CalendarWeekRule.FirstFullWeek, startOfWeek);
    var d1PlusRemainingWeekNo = cal.GetWeekOfYear(d1.AddDays(remainingDays), CalendarWeekRule.FirstFullWeek, startOfWeek);

    if (d1WeekNo != d1PlusRemainingWeekNo)
        weeks++;

    return weeks;
}

【讨论】:

  • 您的解决方案也有效。我使用它是因为您允许设置一周的开始。
【解决方案2】:
static void Main(string[] args)
{
    DateTime date1 = new DateTime(2018, 04, 18);
    DateTime date2 = new DateTime(2018, 04, 19);


    System.Console.WriteLine((GetDiff(new DateTime(2018, 04, 18), new DateTime(2018, 04, 18)))); // 0
    System.Console.WriteLine((GetDiff(new DateTime(2018, 04, 22), new DateTime(2018, 04, 23)))); // 1
    System.Console.WriteLine((GetDiff(new DateTime(2018, 04, 16), new DateTime(2018, 04, 22)))); // 0
    System.Console.WriteLine((GetDiff(new DateTime(2018, 04, 18), new DateTime(2018, 05, 03)))); // 2
}

private static int GetDiff(DateTime date1, DateTime date2)
{
    date1 = SetDayToMonday(date1);
    date2 = SetDayToMonday(date2);

    return (int)((date2 - date1).TotalDays / 7);
}

private static DateTime SetDayToMonday(DateTime date)
{ 
    var weekDay = date.DayOfWeek;
    if (weekDay == DayOfWeek.Sunday)
        return date.AddDays(-6);
    else
        return date.AddDays(-((int)weekDay-1));
}

首先,将日期设置为本周的星期一。然后计算所有整周(= /7 days as int)。虽然很简单,但它可能会持续数周甚至数年。

【讨论】:

    【解决方案3】:

    看看这是否有效。可能还有更多未涵盖的用例,解决方案取决于您如何定义周边界(根据上述评论假设周日至周一)。

    // Output:
    // Weeks between 12/28/2017 and 1/10/2018: 2
    // Weeks between 4/13/2018 and 4/16/2018: 1
    // Weeks between 4/21/2018 and 4/22/2018: 0
    // Weeks between 4/22/2018 and 4/23/2018: 1
    
    void Main()
    {
        var datePairs = new List<KeyValuePair<DateTime, DateTime>>();
        datePairs.Add(new KeyValuePair<DateTime, DateTime>(new DateTime(2017, 12, 28), new DateTime(2018, 1, 10)));
        datePairs.Add(new KeyValuePair<DateTime, DateTime>(new DateTime(2018, 4, 13), new DateTime(2018, 4, 16)));
        datePairs.Add(new KeyValuePair<DateTime, DateTime>(new DateTime(2018, 4, 21), new DateTime(2018, 4, 22)));
        datePairs.Add(new KeyValuePair<DateTime, DateTime>(new DateTime(2018, 4, 22), new DateTime(2018, 4, 23)));
    
        foreach (var datePair in datePairs)
        {
            var string1 = datePair.Key.ToShortDateString();
            var string2 = datePair.Value.ToShortDateString();
            Console.WriteLine($"Weeks between {string1} and {string2}: {GetWeekDiff(datePair.Key, datePair.Value)}");
        }
    }
    
    public static int GetWeekDiff(DateTime dtStart, DateTime dtEnd)
    {
        var totalDays = (dtEnd - dtStart).TotalDays;
        var weeks = (int)totalDays / 7;
        var hasRemainder = totalDays % 7 > 0;
        if (hasRemainder)
        {
            if (!(dtStart.DayOfWeek.Equals(DayOfWeek.Saturday) && dtEnd.DayOfWeek.Equals(DayOfWeek.Sunday)))
            {
                weeks++;
            }
        }
        return weeks;
    }
    

    【讨论】:

    • 不处理同一周内的两个不同日期,应该返回 0。
    • @DanWilson感谢您的回答!我试过了,做了一些测试,到目前为止它似乎工作正常。
    • @DanWilson 仍然不能正确处理同一周内的日期Weeks between 13/04/2018 and 14/04/2018: 1
    • 对不起,我失败了。 :(
    【解决方案4】:

    也许能帮上忙

        public static int GetIso8601WeekOfYear(DateTime time)
        {
            // Seriously cheat.  If its Monday, Tuesday or Wednesday, then it'll 
            // be the same week# as whatever Thursday, Friday or Saturday are,
            // and we always get those right
            DayOfWeek day = CultureInfo.InvariantCulture.Calendar.GetDayOfWeek(time);
            if (day >= DayOfWeek.Monday && day <= DayOfWeek.Wednesday)
            {
                time = time.AddDays(3);
            }
    
            // Return the week of our adjusted day
            return CultureInfo.InvariantCulture.Calendar.GetWeekOfYear(time, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday);
        }
    

    Get the correct week number of a given date

    【讨论】:

      【解决方案5】:

      还不能发表评论,并且已经在这篇文章中使用了我认为类似的标记。这是我发现的另一篇文章,似乎与您尝试创建的解决方案一致:

      Get the number of calendar weeks between 2 dates in C#

      【讨论】:

        【解决方案6】:

        这是我解决类似问题的实现,我没有彻底测试过,但它似乎有效。

                var dt1 = DateTime.Today.AddDays(-30);
                var dt2 = DateTime.Today;
        
                var noOfDays =(int) (dt2 - dt1).TotalDays;
                int reminder;
                var weeks = Math.DivRem(noOfDays, 7, out reminder);
                weeks = reminder > 0 ? weeks + 1 : weeks;
        

        它返回 1 周,间隔 6 天或更短,这正是我所需要的。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-09-22
          • 1970-01-01
          • 2016-03-20
          • 2014-10-12
          • 1970-01-01
          相关资源
          最近更新 更多