从日期列表中获取时间范围

时间:2017-04-08 07:28:48

标签: c# asp.net

我目前想要从日期列表中获取日期范围(在时间范围之间)。

例如:

现在的时间是

  

2017-04-08 18:00

我得到了这些日期:

public static string[] fromDates = new string[] { "2017-04-07 07:00", "2017-04-07 10:00", "2017-04-07 12:00", "2017-04-07 14:00", "2017-04-07 16:00" };
public static string[] toDates = new string[] { "2017-04-07 08:00", "2017-04-07 11:00", "2017-04-07 13:00", "2017-04-07 15:00", "2017-04-07 17:00" };

我正在使用此代码:

public static bool IsInRange(this DateTime dateToCheck, string[] startDates, string[] endDates, out string StartDate, out string EndDate)
    {
        DateTime startDate = new DateTime();
        DateTime endDate = new DateTime();

        bool isWithinRange = false;

        for (int i = 0; i < startDates.Length; i++)
        {
            startDate = Convert.ToDateTime(startDates[i]);

            isWithinRange = dateToCheck >= startDate;

            if (isWithinRange)
                break;
        }

        for (int y = 0; y < endDates.Length; y++)
        {
            endDate = Convert.ToDateTime(endDates[y]);

            isWithinRange = dateToCheck < endDate;

            if (isWithinRange)
                break;
        }

        StartDate = startDate;
        EndDate = endDate;

        return isWithinRange;
    }

我称之为:

var isBetween = Convert.ToDateTime("2017-04-08 18:00").IsInRange(fromDates, toDates, out StartDate, out EndDate)

但我无法使其工作,StartDate方法中的IsInRange始终返回true,它将返回fromDates变量的第一个索引,这是错误的。

我怎样才能让它像中间的那样?

我知道我可以这样做:

var isBetween = dateToCheck >= startDate && dateToCheck < endDate

但是只需要检查一个日期,如果它与我的情况相符怎么样?

你的回答非常感谢。

由于

2 个答案:

答案 0 :(得分:3)

我首先将所有内容转换为更有用的对象模型:

  • 摆脱所有字符串(即在早期将字符串转换为更有用的字符串)
  • 创建一个新类型,指示&#34;日期/时间范围&#34;而不是拥有两个集合。通过将错误的项目放在一起会使您感到有些挫败:起始值彼此不相关,它们与相应的结束日期相关。

如果你真的需要,你可以在方法中执行此操作,但最好尽可能多地移动到更丰富的对象模型。例如,假设你有:

public sealed class DateTimeRange
{
    public DateTime Start { get; }
    public DateTime End { get; }

    public DateTimeRange(DateTime start, DateTime end)
    {
        // TODO: Validate that start <= end
        Start = start;
        End = end;
    }

    public bool Contains(DateTime value) => Start <= value && value < End;
}

然后您的方法可能如下所示:

public DateTimeRange FindRange(IEnumerable<DateTimeRange> ranges, DateTime value) =>
    ranges.FirstOrDefault(range => range.Contains(value));

如果没有范围包含该值,则返回null,否则返回 包含值的第一个值。

(顺便说一句,我在Noda Time做了所有这些,而不是更好的日期/时间API,但我有偏见。)

答案 1 :(得分:1)

如果你想继续使用yoir设计,那么你应该简单地在一个循环中做所有事情,而不是做两次,因为你总是想要将第一个元素与第一个元素匹配,第二个元素与第二个元素相匹配等。

public static bool IsInRange(this DateTime dateToCheck, string[] startDates, string[] endDates, out DateTime StartDate, out DateTime EndDate)
    {
        if (startDates.Length != endDates.Length)
        {
            throw new ArgumentException("The arrays must have the same length");
        }
        StartDate = new DateTime();
        EndDate = new DateTime();

        for (int i = 0; i < startDates.Length; i++)
        {
            StartDate = Convert.ToDateTime(startDates[i]);
            EndDate = Convert.ToDateTime(endDates[i]);

            if (dateToCheck >= StartDate && dateToCheck <= EndDate)
            {
                return true;
            }
        }

        return false;
    }

但正如其他答案中已经说明的那样 - 你应该重新设计你的代码,因为它不是很易维护和易于理解