2010-09-17 11 views
100

Je génère des graphiques multi-séries avec la date le long de l'axe X.Créer un tableau ou une liste de toutes les dates entre deux dates

Le problème est que toutes les séries du graphique n'ont pas les mêmes dates dans la plage de dates. Cela signifie que si je choisis du 1er février au 30 avril, une série peut avoir des données qui commencent au 1er février mais qui ne vont que jusqu'à la fin du mois de mars, mais une autre série peut contenir des données pour toute la période.

Cela fausse les graphiques que j'ai besoin de créer. Allez, compte tenu de la plage de dates prise au début de la requête, je voudrais générer une liste de dates et remplir les données à représenter, en complétant ces séries avec des 0 pour les dates qui n'ont pas de données.

+0

¿Comment représentez-vous les timeseries? – rpax

Répondre

221

LINQ:

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

boucle For:

var dates = new List<DateTime>(); 

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

EDIT: En ce qui concerne les valeurs de remplissage avec les valeurs par défaut dans une série chronologique, vous pourriez énumérer toutes les dates de la date complète, et choisissez la valeur d'une date directement dans la série si elle existe, ou la valeur par défaut dans le cas contraire. Par exemple:

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

Je suis l'exemple LINQ jusqu'à l'instruction 'Select'. Que se passe-t-il exactement là-bas? – Cody

+6

Si vous voulez une plage qui dure 5 jours, par exemple 4/9 - 4/13, l'appel à Enumerable.Range créerait une collection {0,1,2,3,4}. L'instruction select prend cette collection et, pour chaque élément, ajoute cette valeur à la date de début et renvoie la nouvelle date. # 4/9/2012 # .AddDays (0) = 4/9/2012, # 4/9/2012 # .AddDays (1) = 4/10/2012, # 4/9/2012 # .AddDays (2) = 4/11/2012, et ainsi de suite, générant ainsi la gamme de dates. –

+6

Vous devriez probablement utiliser 'TotalDays' et pas' 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

Si vous voulez comparer uniquement la partie Date, modifiez la condition while : while (startDate.Date <= endDate.Date). Sinon, vous obtiendrez une plage différente en fonction de la façon dont la valeur DateTime est construite. –

+0

Puisque la boucle devrait se terminer quand elle est égale à la date de fin parce que nous avons besoin de dates entre deux début et fin donc la date de fin ne devrait pas inclure mais la condition <= retourne aussi enddate. –

1

Notre maestro résident Jon Skeet a un grand Range Class qui peut le faire pour DateTimes et d'autres types.

19

Je sais que c'est un ancien poste, mais essayez d'utiliser une méthode d'extension:

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

et l'utiliser comme ceci

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

Sentez-vous libre de choisir vos propres dates, vous n'avez pas de vous limiter à Janvier 2000.

+0

Ah, aime les méthodes d'extension. – Gustav

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