2010-09-17 17 views
100

Generuję wykresy z wieloma seriami z datą wzdłuż osi X.Utwórz tablicę lub listę wszystkich dat między dwiema datami

Problem polega na tym, że nie wszystkie serie na wykresie mają te same daty w zakresie dat. Oznacza to, że jeśli wybiorę od 1 lutego do 30 kwietnia, jedna seria może mieć dane rozpoczynające się 1 lutego, ale tylko do końca marca, ale inna seria może zawierać dane dla całego zakresu dat.

To pochyla wykresy, które muszę utworzyć. Idź, biorąc pod uwagę zakres dat podjętych na początku zapytania, chciałbym wygenerować listę dat i zapełnić dane do wykreślenia, dopełniając tych serii wartościami zerowymi dla tych dat, które nie mają danych.

+0

¿Jak reprezentujesz przedziały czasowe? – rpax

Odpowiedz

221

LINQ:

Enumerable.Range(0, 1 + end.Subtract(start).Days) 
      .Select(offset => start.AddDays(offset)) 
      .ToArray(); 

Dla pętli:

var dates = new List<DateTime>(); 

for (var dt = start; dt <= end; dt = dt.AddDays(1)) 
{ 
    dates.Add(dt); 
} 

EDIT: chodzi o wartości dopełnienia z domyślnych w szeregach czasowych, można wyliczyć wszystkie daty pełny zakres dat i wybierz wartość dla daty bezpośrednio z serii, jeśli istnieje, lub domyślnie w przeciwnym razie. Na przykład:

var paddedSeries = fullDates.ToDictionary(date => date, date => timeSeries.ContainsDate(date) 
               ? timeSeries[date] : defaultValue); 
+0

Podążam za przykładem LINQ aż do instrukcji 'Select'. Co dokładnie się tam dzieje? – Cody

+6

Jeśli chcesz, aby zakres obejmował 5 dni, na przykład 4/9 - 4/13, wywołanie funkcji Enumerable.Range utworzyłoby kolekcję {0,1,2,3,4}. Instrukcja select pobiera tę kolekcję i dla każdego elementu dodaje tę wartość do daty początkowej i zwraca nową datę. # 4/9/2012 # .AddDays (0) = 4/9/2012, # 4/9/2012 #AddDays (1) = 4/10/2012, # 4/9/2012 #AddDays (2) = 4/11/2012, i tak dalej, generując w ten sposób zakres dat. –

+6

Powinieneś prawdopodobnie używać 'TotalDays', a nie' Days' – yellowblood

28
public static IEnumerable<DateTime> GetDateRange(DateTime startDate, DateTime endDate) 
{ 
    if (endDate < startDate) 
     throw new ArgumentException("endDate must be greater than or equal to startDate"); 

    while (startDate <= endDate) 
    { 
     yield return startDate; 
     startDate = startDate.AddDays(1); 
    } 
} 
+0

Jeśli chcesz porównać tylko część Data, zmodyfikuj warunek while : while (startDate.Date <= endDate.Date). W przeciwnym razie otrzymasz inny zakres w zależności od sposobu skonstruowania wartości DateTime. –

+0

Ponieważ pętla powinna kończyć się, gdy jest równa dacie końcowej, ponieważ potrzebujemy dat między dwoma początkami i końcem, więc data zakończenia nie powinna zawierać, ale warunek <= również zwraca datę końcową. –

1

Nasz rezydent maestro Jon Skeet ma wielką Range Class że może zrobić to za DateTimes i innych typów.

19

Wiem, że to stary post, ale spróbuj użyć metodę rozszerzenia:

public static IEnumerable<DateTime> Range(this DateTime startDate, DateTime endDate) 
    { 
     return Enumerable.Range(0, (endDate - startDate).Days + 1).Select(d => startDate.AddDays(d)); 
    } 

i używać go jak ten

var dates = new DateTime(2000, 1, 1).Range(new DateTime(2000, 1, 31)); 

Poczuj swobodę wyboru własnych dat, nie masz ograniczać się do stycznia 2000.

+0

Ah, metody przedłużania miłości. – Gustav

2
list = list.Where(s => s.startDate >= Input_startDate && s.endDate <= Input_endDate); 

 

Powiązane problemy