Як дізнатися, чи є DateTime між DateRange у C #


79

Мені потрібно знати, чи є дата між DateRange. У мене три побачення:

// The date range
DateTime startDate;
DateTime endDate;

DateTime dateToCheck;

Найпростішим рішенням є порівняння, але чи є розумніший спосіб зробити це?


1
Розумніший спосіб, а потім просто перевірити, чи є дата між цими датами?
Томаш Янссон,

4
То що розумніше простого рішення?
Поліфун

Відповіді:


136

Ні, просте порівняння мені здається непоганим:

return dateToCheck >= startDate && dateToCheck < endDate;

Про що слід подумати:

  • DateTimeє дещо дивним типом з точки зору часових поясів. Це може бути UTC, це може бути "локально", це може бути неоднозначно. Обов’язково порівнюйте яблука з яблуками.
  • Подумайте, чи мають бути ваші початкові та кінцеві точки всеохоплюючими чи ексклюзивними. Я змусив наведений вище код розглядати його як включну нижню межу та ексклюзивну верхню межу.

Так. DateTimeВажливо переконатися, що порівнювані вами товари однакові (UTC / Local) важливо. З різними видами порівнюватиметься необроблений час замість того, щоб перетворювати обидва на загальний вид.
CodesInChaos

6
return startDate <= dateToCheck && dateToCheck < endDateздається трохи читабельнішим.
Mauricio Morales

7
@MauricioMorales: Це залежить; деяким людям легше читати "біт, що змінюється" (дату перевірки), постійно на лівій стороні. Це те, що я схильний робити. Я також бачу переваги підходу "у хронологічному порядку", але я думаю, що я б особисто віддав перевагу тому, як я його маю.
Джон Скіт,

64

Зазвичай для таких речей я створюю реалізацію діапазону Фаулера .

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
Просто безглузде спостереження, чи не потрібно конструктору гарантувати, що початок менше кінця, якщо цього не стане, це порушить логіку ... особливо щодо Включає (діапазон IRange <DateTime>)
Адріан Хам,

2
Людина, це настільки гарне рішення, що навіть працює з LINQ. Ось так: var valueFromVacationsList = holidayBookingsForThisMonth.FirstOrDefault (s => (s.Id == currentUser.Id) && new DateRange (s.StartDateTime, s.EndDateTime) .Включає (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

Я використовував бібліотеку "Час часу" для проекту, який створював графіки, коли електронні вивіски мали відображати зображення, і це заощаджувало час. Чорт возьми, я не можу собі уявити, що закінчив цей проект без бібліотеки «Часовий період».
PoorInRichfield

2

Слідом за Сергій відповіді , я думаю , що це більш загальний варіант більш відповідно до Фаулером Rangeідеєю, і вирішує деякі з проблем , з цією відповіддю , такими як можливість мати Includesметоди в узагальненому класі шляхом обмеження , Tяк 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;
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.