2017-04-08 70 views
1

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

例如:

现在的时间是

2017年4月8日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) 

但我不能让它工作,在StartDateIsInRange方法总是返回true,将它从fromDates变量,它是返回的第一个索引错误。

我怎样才能让它像之间的时间?

我知道我能做到这一点是这样的:

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

但它只有一个日期需要检查,那如果是喜欢我的情况?

您的回答非常感谢。

感谢

回答

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; 
    } 

但在其他答案已经指出 - 你应该重新设计你的代码,因为它不是很maintenable且易于理解

+0

我正准备发布这些确切的更改:) –

+0

感谢您的回答和建议@Pawel Gradecki,我想接受你的答案,但他们(stackoverflow)不是允许我这样做:)。将尝试乔恩Skeet的建议和你的重新设计我的代码。 – Trinity

+0

请注意,代码目前不会编译 - 循环后的'return'语句需要*。我建议你根本不需要'isWithinRange',但如果你到达循环结尾,你可以返回'true'而不是'break'语句,并且返回false。 –

3

我会通过一切转换成一个有用的对象模型开始:

  • 摆脱所有的字符串(即转换从字符串到更有用的东西早)
  • 相反有两个集合,创建一个新类型,指示“日期/时间范围”。通过将错误的项目联系在一起,你有些被挫败:起始值彼此没有关系,它们与其相应的结束日期有关。

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

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,但我有点偏颇。)

+0

感谢您的建议@乔恩飞碟双向,我想同时接受你的答案,但他们是(stackoverflow)不允许我这样做:)。将尝试重新设计我的代码作为您的建议 – Trinity