2009-08-06 8 views
1

J'ai une liste contenant 60 DateTime objets (triés par ordre croissant) et devez valider que chaque date est 1 mois plus grand que le précédent dans la liste.Date de validation sont séquentielles par mois

Par exemple, la liste suivante des dates serait valable parce qu'ils incrémenter d'un mois avec aucun manque:

Jan-2009
Feb-2009
Mar-2009
Avr-2009

Cependant, la liste suivante des dates serait invalide parce que Feb-2009 est manquante:

Jan-2009
Mar-2009
avril-2009

Le jour n'a pas d'importance, juste le mois et année sont considérés.

Existe-t-il une façon efficace/jolie de le faire?

Répondre

3

Vous pouvez essayer ce qui suit:

int start = list.First().Year * 12 + list.First().Month; 
bool sequential = list 
    .Select((date, index) => date.Year * 12 + date.Month - index) 
    .All(val => val == start); 

Ce « convertit » la liste des dates en un nombre qui représente l'année et le mois, qui devrait être incrémente de 1 pour chaque élément dans la liste . Nous soustrayons ensuite l'index actuel de chacun de ces éléments, donc pour une liste valide, tous les éléments auront la même valeur. Nous comparons ensuite toutes les valeurs à start, qui est la première valeur calculée.

8

Pour toutes les dates, si vous prenez (année * 12 + mois) vous obtiendrez une liste séquentielle d'entiers. Cela pourrait être plus facile de vérifier les lacunes.

+1

+1 est mieux Simpler. –

0
public bool MonthsAreSequential(IList<DateTime> dates) 
{ 
    if (dates.Count < 2) return true; 

    for (int i = 0; i < dates.Count - 1; i++) 
    { 
     var plusOne = dates[i].AddMonth(1); 
     var nextMonth = dates[i + 1]; 
     if (plusOne .Year != nextMonth .Year 
      || plusOne .Month != nextMonth .Month) 
      return false; 
    } 
    return true; 
} 
+1

Simultané: en fonctionnement ou se produisant en même temps; Séquentiel: de, lié à, ou organisé dans une séquence (http://www.merriam-webster.com/dictionary) – grenade

+0

Doh, mon mauvais. Je me suis mélangé. –

1

est ici un chèque propre, faisant usage d'un sélecteur soigneusement conçu qui comparera correctement pour votre cas d'utilisation:

IEnumerable<DateTime> dates = ...; 
DateTime firstDate = dates.First(); 
IEnumerable desired = Enumerable.Range(0, 60).Select(months => firstDate.AddMonths(months)); 
bool correct = dates.SequenceEqual(desired, date => date.Year*12 + date.Month); 

En utilisant cette coutume SequenceEqual:

public static bool SequenceEqual<T1, T2>(this IEnumerable<T1> first, IEnumerable<T1> second, Func<T1, T2> selector) 
{ 
    // uses the LINQ Enumerable.SequenceEqual method on the selections 
    return first.Select(selector).SequenceEqual(second.Select(selector)); 
} 

// this is also useful, but not used in this example 
public static bool SequenceEqual<T1, T2>(this IEnumerable<T1> first, IEnumerable<T1> second, Func<T1, T2> selector, IEqualityComparer<T2> comparer) 
{ 
    return first.Select(selector).SequenceEqual(second.Select(selector), comparer); 
} 
Questions connexes