检查一个日期时间是否与另一个日期时间在同一周

15
假设我有一个表格里面包含了一些日期。现在我想要找到所有与提供日期参数相同星期的行。
比如说,我有这样一个表格:
  • 2014-09-11
  • 2014-09-12
  • 2014-09-15
如果我将 2014-09-09 作为参数传入,函数就需要从周一到周日查找,并且确定 09-11 和 09-12 是本周的一部分,但是 09-15 不是。
那么,应该怎样解决这个问题呢?
我考虑过检查年、月和周数,但是不能保证月份相同...
那么,究竟该怎么办才能解决这个问题呢?

将其解析为日期时间对象并从中提取一年中的周数? - SiKing
请问如何获取一周的开始时间日期? - thumbmunkeys
1
http://msdn.microsoft.com/en-us/library/system.globalization.calendar.getweekofyear.aspx - Sagar Pilkhwal
根据您所在的地区,一周的起始日可能不同:周日和周一是常见的。 - Sergey Kalinichenko
9个回答

23

DxCk的评论是有效的。即使一年的第一周或最后一周跨越两个不同的年份,此解决方案也能正常工作:

检查两个日期的第一天是否落在同一天。

以下是代码:

    private bool DatesAreInTheSameWeek(DateTime date1, DateTime date2)
    {
        var cal = System.Globalization.DateTimeFormatInfo.CurrentInfo.Calendar;
        var d1 = date1.Date.AddDays(-1 * (int)cal.GetDayOfWeek(date1));
        var d2 = date2.Date.AddDays(-1 * (int)cal.GetDayOfWeek(date2));

        return d1 == d2;
    }

1
只有在你希望周从星期天开始时,这个方法才能起作用。 - Electric Sheep
1
@OllieP,你可以通过从星期减去1来轻松解决这个问题:date1.AddDays(-((int)date1.DayOfWeek-1))。在我看来,这应该是被接受的答案。 - Simon Hänisch
我宁愿创建一个小的辅助方法,返回我所在地区适当的工作日数字,而不是从DayOfWeek中“神奇地减去”,因为这需要人们知道内置枚举从星期日开始。 - Arve Systad
@Sparrow,你的解决方案在星期从周一开始的国家无法正确执行。请尝试使用2020年1月11日和2020年6月11日的上述代码。 - SHS
你只想比较日期到天的精度(不包括小时等),因此最后一行应该是:return d1.Date == d2.Date; - Yiorgos
不适用于法国日历,例如03/10/2022和9/10/2022。 - Aminos

10

为什么不呢?

bool AreFallingInSameWeek(DateTime date1, DateTime date2)
{
    return date1.AddDays(-(int)date1.DayOfWeek) == date2.AddDays(-(int)date2.DayOfWeek);
}

如果你想使用周的起始日为除了星期天以外的其他日子

bool AreFallingInSameWeek(DateTime date1, DateTime date2, DayOfWeek weekStartsOn)
{
    return date1.AddDays(-GetOffsetedDayofWeek(date1.DayOfWeek, (int)weekStartsOn)) == date2.AddDays(-GetOffsetedDayofWeek(date2.DayOfWeek, (int)weekStartsOn));
}

int GetOffsetedDayofWeek(DayOfWeek dayOfWeek, int offsetBy)
{
    return (((int)dayOfWeek - offsetBy + 7) % 7)
}

1
在 .Net Core 中使用 DateTime 时应该注意,毫秒数几乎总会导致返回 false,例如:AreFallingInSameWeek(DateTime.Now, DateTime.Now, DayOfWeek.Monday) 将会返回 false,但是你可以通过添加 .Date 来解决这个问题,如下所示:date1.AddDays(-GetOffsetedDayofWeek(date1.DayOfWeek, (int)weekStartsOn)).Date == date2.AddDays(-GetOffsetedDayofWeek(date2.DayOfWeek, (int)weekStartsOn)).Date; - Shoejep
在这两种解决方案中,第一种会返回 false,因为它也比较了时间。只需在两个值的结尾添加 .Date 即可仅比较日期,代码如下: return date1.AddDays(-(int)date1.DayOfWeek).Date == date2.AddDays(-(int)date2.DayOfWeek).Date; - david-so

4

检查DateTime.Year和Calendar.GetWeekOfYear(DateTime, ...)。不需要检查月份。

编辑:这是错误的,但我无法删除它。请参见下面@Sparrow的答案。


10
2015年12月31日和2016年1月1日在同一周但不同年份,怎么处理? - DxCK

3

使用 Calendar 类的 public virtual int GetWeekOfYear(DateTime time, CalendarWeekRule rule, DayOfWeek firstDayOfWeek) 方法


2

我的要求是找到本周出生日期。希望这可以解决你的疑惑。基本上,这段代码背后的思想如下:

  1. Change the DOB to current year birthday (eg; 24-02-1988 to 24-02-2018(current year).
  2. Add a year, if the brithday week contains both dec and jan
  3. Get the first day of today's week.
  4. Get last day of today's week.
  5. check if the current year birthday falls between first day and last day of today's week.

    private bool DatesAreInTheSameWeek(DateTime birthday)
    {
        if (birthday == DateTime.MinValue)
        {
            return false;
        }
        else
        {
            var birtdayWithCurrentYear = new DateTime(DateTime.Today.Year, birthday.Month, birthday.Day);
            if (birthday.Month == 1 && DateTime.Today.Month != 1)
            {
                birtdayWithCurrentYear = birtdayWithCurrentYear.AddYears(1);
            }
            DateTime firstDayInWeek = DateTime.Today.Date;
            while (firstDayInWeek.DayOfWeek != CultureInfo.CurrentCulture.DateTimeFormat.FirstDayOfWeek)
                firstDayInWeek = firstDayInWeek.AddDays(-1);var lastDayInWeek = firstDayInWeek.AddDays(7);
    
            return birtdayWithCurrentYear < lastDayInWeek && birtdayWithCurrentYear >= firstDayInWeek;
    
        }
    }
    

1
找到第一个日期所在周的开始和结束日期。然后检查第二个日期是否在这两个日期之间。
   public static bool DateInsideOneWeek(DateTime date1, DateTime date2)
    {
        DayOfWeek firstDayOfWeek = System.Globalization.CultureInfo.CurrentCulture.DateTimeFormat.FirstDayOfWeek;
        DateTime startDateOfWeek = date1.Date;
        while(startDateOfWeek.DayOfWeek != firstWeekDay)
        { startDateOfWeek = startDateOfWeek.AddDays(-1d); }
        DateTime endDateOfWeek = startDateOfWeek.AddDays(6d);
        return date2 >= startDateOfWeek && date2 <= endDateOfWeek;
    }

我尝试过这个方法,但是在检查日期时遇到了一些问题,因为要检查的日期还包含时间。所以我添加了startDateOfWeek.AddHours(-startDateOfWeek.Hour)来去除小时数,同样的方法也用于分钟数,然后endDateOfWeek = startDateOfWeek.AddDays(7d),这样我就得到了从午夜开始到一周后午夜结束的日期。这对我很有效。谢谢! - Peter Thaus

1

由于被接受的答案中存在错误,正如@DxCK在评论中提到的那样,这里是我的解决方案:

public static class DateExtensions
{
    private static void Swap<T>(ref T one, ref T two)
    {
        var temp = one;
        one = two;
        two = temp;
    }

    public static bool IsFromSameWeek(this DateTime first, DateTime second, DayOfWeek firstDayOfWeek = DayOfWeek.Monday)
    {
        // sort dates
        if (first > second)
        {
            Swap(ref first, ref second);
        }

        var daysDiff = (second - first).TotalDays;
        if (daysDiff >= 7)
        {
            return false;
        }

        const int TotalDaysInWeek = 7;
        var adjustedDayOfWeekFirst = (int)first.DayOfWeek + (first.DayOfWeek < firstDayOfWeek ? TotalDaysInWeek : 0);
        var adjustedDayOfWeekSecond = (int)second.DayOfWeek + (second.DayOfWeek < firstDayOfWeek ? TotalDaysInWeek : 0);

        return adjustedDayOfWeekSecond >= adjustedDayOfWeekFirst;
    }
}

这里还有一个正确的解决方案链接,使用了稍微不同的方法。

0

如果您不想使用日历类,可以使用此函数:

public static int WeekOfYear(DateTime dt)
{
    int startDays = 0;
    // first day of the year
    DateTime firstJanuary = new DateTime(dt.Year, 1, 1);

    if (firstJanuary.DayOfWeek == DayOfWeek.Tuesday)
    {
        startDays = 1;
    } 
    else if (firstJanuary.DayOfWeek == DayOfWeek.Wednesday)
    {
        startDays = 2;
    }
    else if (firstJanuary.DayOfWeek == DayOfWeek.Thursday)
    {
        startDays = 3;
    }
    else if (firstJanuary.DayOfWeek == DayOfWeek.Friday)
    {
        startDays = 4;
    }
    else if (firstJanuary.DayOfWeek == DayOfWeek.Saturday)
    {
        startDays = 5;
    }
    else if (firstJanuary.DayOfWeek == DayOfWeek.Sunday)
    {
        startDays = 6;
    }

    if (DateTimeFormatInfo.CurrentInfo.FirstDayOfWeek == DayOfWeek.Sunday)
    {
        startDays++;
        startDays = startDays % 7;
    }

    return ((dt.DayOfYear + startDays - 1) / 7) + 1;
}

0

接受的答案对于法国日历和日期为 2022 年 03 月 10 日和 2022 年 10 月 09 日时不起作用。

以下内容适用于我:

    public static partial class DateTimeExtensions
    {
        public static DateTime FirstDayOfWeek(this DateTime dt)
        {
            var culture = System.Threading.Thread.CurrentThread.CurrentCulture;
            var diff = dt.DayOfWeek - culture.DateTimeFormat.FirstDayOfWeek;

            if (diff < 0)
            {
                diff += 7;
            }

            return dt.AddDays(-diff).Date;
        }

        public static DateTime LastDayOfWeek(this DateTime dt) =>
            dt.FirstDayOfWeek().AddDays(6);

        public static DateTime FirstDayOfMonth(this DateTime dt) =>
            new DateTime(dt.Year, dt.Month, 1);

        public static DateTime LastDayOfMonth(this DateTime dt) =>
            dt.FirstDayOfMonth().AddMonths(1).AddDays(-1);

        public static DateTime FirstDayOfNextMonth(this DateTime dt) =>
            dt.FirstDayOfMonth().AddMonths(1);

        public static int GetWeeekNumber(this DateTime dt)
        {
            CultureInfo culture = System.Threading.Thread.CurrentThread.CurrentCulture;
            Calendar myCal = culture.Calendar;

            // Gets the DTFI properties required by GetWeekOfYear.
            CalendarWeekRule myCWR = culture.DateTimeFormat.CalendarWeekRule;
            DayOfWeek myFirstDOW = culture.DateTimeFormat.FirstDayOfWeek;

            return myCal.GetWeekOfYear(dt, myCWR, myFirstDOW);
        }

        public static bool IsInTheSameWeek(this DateTime date1, DateTime date2)
        {
            return date1.GetWeeekNumber() == date2.GetWeeekNumber();
        }
    }

使用方法:

item.Week.IsInTheSameWeek(Week)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接