2010-08-02 29 views
8

Tôi đang cố gắng tìm ngày thiếu giữa hai biến DateTime cho một tập hợp DateTimes.Tìm ngày bị thiếu trong một phạm vi nhất định

Ví dụ:

Collection 
2010-01-01 
2010-01-02 
2010-01-03 
2010-01-05 

DateRange 
2010-01-01 -> 2010-01-06 

sẽ cung cấp cho tôi một List<DateTime> của

2010-01-04 
2010-01-06 

tôi có thể nghĩ ra một vài đã thực hiện điều này nhưng không sạch và đơn giản

Bất kỳ ý tưởng?

Trả lời

16

tôi có thể nghĩ ra rất nhiều cách để thực hiện điều này, ví dụ:

DateTime[] col = { new DateTime(2010, 1, 1), 
        new DateTime(2010, 1, 2), 
        new DateTime(2010, 1, 3), 
        new DateTime(2010, 1, 5)}; 

var start = new DateTime(2010, 1, 1); 
var end = new DateTime(2010, 1, 6); 

var range = Enumerable.Range(0, (int)(end - start).TotalDays + 1) 
         .Select(i => start.AddDays(i)); 

var missing = range.Except(col); 

Và bạn có thể đặt phạm vi-thứ vào một Extension-Phương pháp

public static class extensions 
{ 
    public static IEnumerable<DateTime> Range(this DateTime startDate, DateTime endDate) 
    { 
     return Enumerable.Range(0, (int)(endDate - startDate).TotalDays + 1) 
         .Select(i => startDate.AddDays(i)); 
    } 
} 

Sau đó, nó sẽ chỉ đơn giản là

DateTime[] col = { new DateTime(2010, 1, 1), 
        new DateTime(2010, 1, 2), 
        new DateTime(2010, 1, 3), 
        new DateTime(2010, 1, 5)}; 

var start = new DateTime(2010, 1, 1); 
var end = new DateTime(2010, 1, 6); 
var missing = start.Range(end).Except(col); 

Nhưng có lẽ đây không phải là một hiệu suất-giải pháp cao :-)

+0

Thats tương tự như những gì tôi đã suy nghĩ ngoại trừ việc sử dụng một vòng lặp for để xây dựng phạm vi của tôi. Tôi chỉ không thích ý tưởng xây dựng một danh sách các ngày mỗi lần vì tôi phải làm điều đó rất nhiều. –

+1

+1 Sử dụng tốt phạm vi. – Thomas

+0

Vâng, sử dụng thông minh phạm vi;) –

2

Tùy thuộc vào chính xác nội dung bạn đang tìm kiếm và kích thước của tập hợp dữ liệu. Một cách đơn giản là tải ngày tháng vào bộ sưu tập, sau đó sử dụng một vòng lặp đơn giản. Tôi sẽ thêm một mẫu mã ở đây trong một giây.

DateTime currentDate = new DateTime(2010, 1, 1); 
DateTime endDate = new DateTime(2010, 1, 6); 
List<DateTime> existingDates = new List<DateTime>; //You fill with values 
List<DateTime> missingDates = new List<DateTime>; 

while(currentDate <= endDate) 
{ 
    if(existingDates.contains(currentDate)) 
     missingDates.Add(currentDate); 

    //Increment date 
    currentDate = currentDate.AddDays(1); 
} 

Sử dụng ví dụ này, bạn chỉ cần tải "existingDates" với các giá trị thích hợp, sau đó là "missingDates" danh sách sẽ có kết quả của bạn

+0

có phải là một cách tiếp cận tốt để sử dụng Chứa (..) có? Khớp toàn bộ mảng với một mục trong bản lặp của chính nó. Tôi đã không chuẩn bị, nhưng tôi sẽ đi cho một số truy cập ở đâu và đếm <1 ở đây. – Independent

1
var dates = new List<DateTime> 
       { 
        new DateTime(2010, 01, 01), 
        new DateTime(2010, 01, 02), 
        new DateTime(2010, 01, 03), 
        new DateTime(2010, 01, 05) 
       }; 

var targetDate = new DateTime(2010, 01, 01); 

var missingDates = new List<DateTime>(); 
while (targetDate <= new DateTime(2010, 01, 06)) 
{ 
    if (!dates.Contains(targetDate)) 
     missingDates.Add(targetDate); 

    targetDate = targetDate.AddDays(1); 
} 

foreach (var date in missingDates) 
    Debug.WriteLine(date.ToString()); 

Nếu bạn đang nghĩ đến việc giải quyết này là LINQ, Tôi không tin rằng nó có thể trừ khi bạn cũng đã có một danh sách của tất cả các ngày giữa ngày tối thiểu và tối đa. Trong SQL, điều này dẫn đến một bảng lịch có chứa tất cả các ngày trong một khoảng thời gian nhất định.

Dưới đây là một giải pháp LINQ nơi tôi có thể tạo danh sách Lịch tôi đã đề cập ở trên và sau đó truy vấn cho những ngày mất tích:

var dates = new List<DateTime> 
       { 
        new DateTime(2010, 01, 01), 
        new DateTime(2010, 01, 02), 
        new DateTime(2010, 01, 03), 
        new DateTime(2010, 01, 05) 
       }; 
var calendar = new List<DateTime>(); 
var targetDate = new DateTime(2010, 01, 01); 
while (targetDate <= new DateTime(2010, 01, 06)) 
{ 
    calendar.Add(targetDate); 
    targetDate = targetDate.AddDays(1); 
} 

var missingDates = (from date in calendar 
       where !dates.Contains(date) 
       select date).ToList(); 

foreach (var date in missingDates) 
    Debug.WriteLine(date.ToString()); 
1

Lazy đánh giá hỗ trợ phương pháp helper trong việc tạo danh sách các ngày để so sánh với. Có thể muốn thực hiện hồ sơ phương pháp này cho các bộ sưu tập lớn.

void Main() 
{ 
    var dates = new[] {new DateTime(2000,1,1), new DateTime(2000,1,5)}; 
    DateHelper.Range(new DateTime(2000,1,1), new DateTime(2000,1,5)).Except(dates).Dump(); 
} 

// Define other methods and classes here 
public static class DateHelper { 
    public static IEnumerable<DateTime> Range(DateTime start, DateTime end) { 
     var days = end.Subtract(start).Days; 
     var next = start; 
     for(var i = 0; i<days; i++) { 
      next = next.AddDays(1); 
      yield return next; 
     } 
    } 
} 
4

Trong .NET 2.0 :)

static void Main(string[] args) 
    { 
     List<DateTime> dates = new List<DateTime>(); 
     dates.Add(new DateTime(2010, 01, 27)); 
     dates.Add(new DateTime(2010, 01, 30)); 
     dates.Add(new DateTime(2010, 01, 31)); 
     dates.Add(new DateTime(2010, 02, 01)); 


     DateTime startDate = new DateTime(2010, 01, 25); 
     DateTime endDate = new DateTime(2010, 02, 02); 

     List<DateTime> missingDates = new List<DateTime>(GetMissingDates(dates, startDate, endDate)); 

    } 

    private static IEnumerable<DateTime> GetMissingDates(IList<DateTime> dates, DateTime startDate, DateTime endDate) 
    { 
     TimeSpan _timeStamp = endDate - startDate; 
     DateTime _tempDateTime = startDate; 
     IList<DateTime> _dateTimeRange = new List<DateTime>(); 
     IList<DateTime> _missingDates = new List<DateTime>(); 

     for (int i = 0; i <= _timeStamp.Days; i++) 
     { 
      _dateTimeRange.Add(_tempDateTime); 
      _tempDateTime = _tempDateTime.AddDays(1); 
     } 

     foreach (DateTime dt in _dateTimeRange) 
     { 
      if (!dates.Contains(dt)) 
       yield return dt; 
     } 
    } 
+0

+1 Dành cho 2,0 lần cấy ghép! –

Các vấn đề liên quan