如何知道DateTime是否在C#中的DateRange之间


77

我需要知道Date是否在DateRange之间。我有三个约会:

// The date range
DateTime startDate;
DateTime endDate;

DateTime dateToCheck;

简单的解决方案是进行比较,但是有更聪明的方法吗?


1
然后一种更聪明的方法是仅检查日期是否在这些日期之间?
Tomas Jansson,

4
那么,有什么比简单的解决方案更聪明的呢?
Polyfun 2011年

Answers:


134

不,对我来说做一个简单的比较看起来不错:

return dateToCheck >= startDate && dateToCheck < endDate;

需要考虑的事情:

  • DateTime在时区方面有点奇怪。它可以是UTC,可以是“本地”,也可以是模棱两可的。确保您正在比较苹果和苹果。
  • 考虑您的起点和终点应该是包容性还是排他性。我已经使上面的代码将其视为包含性下限和专有性上限。

是。确保DateTime您比较的s是同一类型(UTC / Local),这一点很重要。对于不同的种类,将比较原始时间,而不是将两者都转换成相同的种类。
CodesInChaos

6
return startDate <= dateToCheck && dateToCheck < endDate似乎更具可读性。
莫里西奥·莫拉莱斯

7
@MauricioMorales:这取决于;有些人发现比较容易理解一致的“变化的部分”(检查的日期)在左侧。那就是我倾向于做的。我也可以看到“按时间顺序”方法的优点,但是我个人认为我更喜欢这种方法。
乔恩·斯基特

64

通常,我会为此类事情创建Fowler's Range实现。

public interface IRange<T>
{
    T Start { get; }
    T End { get; }
    bool Includes(T value);
    bool Includes(IRange<T> range);
}

public class DateRange : IRange<DateTime>         
{
    public DateRange(DateTime start, DateTime end)
    {
        Start = start;
        End = end;
    }

    public DateTime Start { get; private set; }
    public DateTime End { get; private set; }

    public bool Includes(DateTime value)
    {
        return (Start <= value) && (value <= End);
    }

    public bool Includes(IRange<DateTime> range)
    {
        return (Start <= range.Start) && (range.End <= End);
    }
}

用法很简单:

DateRange range = new DateRange(startDate, endDate);
range.Includes(date)

2
只是一个愚蠢的观察,构造函数不需要确保start小于end,如果不是,则会破坏逻辑……尤其是在Includes(IRange <DateTime>范围)上
Adrian Hum

2
伙计,这是一个很好的解决方案,甚至可以与LINQ一起使用。像这样:var valueFromVacationsList = vacationBookingsForThisMonth.FirstOrDefault(s =>(s.Id == currentUser.Id)&& new DateRange(s.StartDateTime,s.EndDateTime).Includes(itemDate));
卡达吉

46

您可以使用扩展方法使其更具可读性:

public static class DateTimeExtensions
{
    public static bool InRange(this DateTime dateToCheck, DateTime startDate, DateTime endDate)
    {
        return dateToCheck >= startDate && dateToCheck < endDate;
    }
}

现在您可以编写:

dateToCheck.InRange(startDate, endDate)

28
不错的办法,但我会用IsInRange()作为函数名
安德鲁

9

您可以使用:

return (dateTocheck >= startDate && dateToCheck <= endDate);

5

我发现以下库在进行任何日期数学运算时最有帮助。我仍然没有感到惊讶,因为这是.Net框架的一部分。

http://www.codeproject.com/Articles/168662/Time-Period-Library-for-NET


我同意。我不敢相信.NET没有本地日期数学程序集。感谢您共享图书馆
BoundForGlory,2016年

我将“时间段”库用于一个项目,该项目为电子标牌应该显示图像的时间表创建了时间表,这是一个真正的节省时间的功能。哎呀,我无法想象没有Time Period库就完成了那个项目。
PoorInRichfield

2

根据Sergey的答案,我认为这个更通用的版本更符合Fowler的Range想法,并解决了该答案的一些问题,例如能够Includes通过将Tas约束为通用类中的方法IComparable<T>。就像您希望扩展其他值类型(如)的功能的类型一样,它也是不可变的DateTime

public struct Range<T> where T : IComparable<T>
{
    public Range(T start, T end)
    {
        Start = start;
        End = end;
    }

    public T Start { get; }

    public T End { get; }

    public bool Includes(T value) => Start.CompareTo(value) <= 0 && End.CompareTo(value) >= 0;

    public bool Includes(Range<T> range) => Start.CompareTo(range.Start) <= 0 && End.CompareTo(range.End) >= 0;
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.