Comment puis-je parcourir une plage de dates?

Je ne suis même pas sûr de savoir comment faire cela sans utiliser une horrible solution de type boucle / compteur. Voici le problème:

On me donne deux dates, une date de début et une date de fin et sur un intervalle spécifié, je dois prendre des mesures. Par exemple: pour chaque date entre le 3/10/2009 tous les trois jours jusqu'au 3/26/2009, je dois créer une entrée dans une liste. Donc, mes entrées seraient:

DateTime StartDate = "3/10/2009";
DateTime EndDate = "3/26/2009";
int DayInterval = 3;

Et ma sortie serait une liste qui a ce qui suit dates:

3/13/2009 3/16/2009 3/19/2009 3/22/2009 3/25/2009

Alors, comment diable ferais-je quelque chose comme ça? J'ai pensé à utiliser une boucle for qui itérerait entre tous les jours dans la plage avec un compteur séparé comme ceci:

int count = 0;

for(int i = 0; i < n; i++)
{
     count++;
     if(count >= DayInterval)
     {
          //take action
          count = 0;
     }

}

Mais il semble qu'il pourrait y avoir un meilleur moyen?

157
demandé sur onekidney 2009-12-04 18:13:17

14 réponses

Eh bien, vous devrez les parcourir d'une manière ou d'une autre. Je préfère définir une méthode comme celle-ci:

public IEnumerable<DateTime> EachDay(DateTime from, DateTime thru)
{
    for(var day = from.Date; day.Date <= thru.Date; day = day.AddDays(1))
        yield return day;
}

, Alors vous pouvez l'utiliser comme ceci:

foreach (DateTime day in EachDay(StartDate, EndDate))
    // print it or whatever

De cette manière, vous pourriez frapper tous les deux jours, tous les trois jours, seulement en semaine, etc. Par exemple, pour revenir tous les trois jours à partir de la date de "début", vous pouvez simplement appeler AddDays(3) dans la boucle au lieu de AddDays(1).

384
répondu mquander 2009-12-04 15:16:02

J'ai une classe Range dans MiscUtil que vous pourriez trouver utile. Combiné avec les différentes méthodes d'extension, vous pouvez faire:

foreach (DateTime date in StartDate.To(EndDate).ExcludeEnd()
                                   .Step(DayInterval.Days())
{
    // Do something with the date
}

(Vous pouvez ou ne voulez pas exclure la fin-je pensais juste que je le fournirais à titre d'exemple.)

Il s'agit essentiellement d'une forme prête à l'emploi (et plus générale) de la solution de mquander.

28
répondu Jon Skeet 2009-12-04 15:18:37

Pour votre exemple, vous pouvez essayer

DateTime StartDate = new DateTime(2009, 3, 10);
DateTime EndDate = new DateTime(2009, 3, 26);
int DayInterval = 3;

List<DateTime> dateList = new List<DateTime>();
while (StartDate.AddDays(DayInterval) <= EndDate)
{
   StartDate = StartDate.AddDays(DayInterval);
   dateList.Add(StartDate);
}
18
répondu Adriaan Stander 2009-12-04 15:17:55

Code de @Mquander et @yogourt le Sage utilisé dans les extensions:

public static IEnumerable<DateTime> EachDay(DateTime from, DateTime thru)
{
    for (var day = from.Date; day.Date <= thru.Date; day = day.AddDays(1))
        yield return day;
}

public static IEnumerable<DateTime> EachMonth(DateTime from, DateTime thru)
{
    for (var month = from.Date; month.Date <= thru.Date || month.Month == thru.Month; month = month.AddMonths(1))
        yield return month;
}

public static IEnumerable<DateTime> EachDayTo(this DateTime dateFrom, DateTime dateTo)
{
    return EachDay(dateFrom, dateTo);
}

public static IEnumerable<DateTime> EachMonthTo(this DateTime dateFrom, DateTime dateTo)
{
    return EachMonth(dateFrom, dateTo);
}
11
répondu Jacob Sobus 2014-09-26 08:21:37
DateTime startDate = new DateTime(2009, 3, 10);
DateTime stopDate = new DateTime(2009, 3, 26);
int interval = 3;

for (DateTime dateTime=startDate;
     dateTime < stopDate; 
     dateTime += TimeSpan.FromDays(interval))
{

}
7
répondu gilbertc 2009-12-04 15:35:47

1 An plus tard, peut-il aider quelqu'un,

Cette version comprend un prédicat, pour être plus flexible.

Utilisation

var today = DateTime.UtcNow;
var birthday = new DateTime(2018, 01, 01);

Tous les jours à mon anniversaire

var toBirthday = today.RangeTo(birthday);  

Mensuel à mon anniversaire, Étape 2 mois

var toBirthday = today.RangeTo(birthday, x => x.AddMonths(2));

Chaque année à mon anniversaire

var toBirthday = today.RangeTo(birthday, x => x.AddYears(1));

Utilisez RangeFrom à la place

// same result
var fromToday = birthday.RangeFrom(today);
var toBirthday = today.RangeTo(birthday);

Mise en œuvre

public static class DateTimeExtensions 
{

    public static IEnumerable<DateTime> RangeTo(this DateTime from, DateTime to, Func<DateTime, DateTime> step = null)
    {
        if (step == null)
        {
            step = x => x.AddDays(1);
        }

        while (from < to)
        {
            yield return from;
            from = step(from);
        }
    }

    public static IEnumerable<DateTime> RangeFrom(this DateTime to, DateTime from, Func<DateTime, DateTime> step = null)
    {
        return from.RangeTo(to, step);
    }
}

Extras

Vous pouvez lancer une Exception si le fromDate > toDate, mais je préfère retourner une plage vide à la place []

4
répondu amd 2017-11-24 08:25:48
DateTime startDate = new DateTime(2009, 3, 10);
DateTime stopDate = new DateTime(2009, 3, 26);
int interval = 3;

while ((startDate = startDate.AddDays(interval)) <= stopDate)
{
    // do your thing
}
3
répondu devnull 2009-12-04 15:24:38

Selon le problème, vous pouvez essayer ceci...

// looping between date range    
while (startDate <= endDate)
{
    //here will be your code block...

    startDate = startDate.AddDays(1);
}

Merci......

2
répondu Rejwanul Reja 2015-04-09 05:45:24

Vous pouvez envisager d'écrire un itérateur à la place, ce qui vous permet d'utiliser une syntaxe de boucle 'for' normale comme '++'. J'ai cherché et trouvé une question similaire répondu ici sur StackOverflow qui donne des pointeurs pour rendre DateTime itérable.

1
répondu REDace0 2017-05-23 12:02:53

Vous pouvez utiliser la fonction DateTime.AddDays() pour ajouter votre DayInterval au StartDate et vérifier qu'il est inférieur au EndDate.

1
répondu TLiebe 2015-08-10 06:55:22
DateTime begindate = Convert.ToDateTime("01/Jan/2018");
DateTime enddate = Convert.ToDateTime("12 Feb 2018");
while (begindate < enddate)
{
    begindate= begindate.AddDays(1);
    Console.WriteLine(begindate + "  " + enddate);
}
1
répondu Sunil Joshi 2018-02-12 15:38:26

Vous devez faire attention ici à ne pas manquer les dates où dans la boucle une meilleure solution serait.

Cela vous donne la première date de startdate et l'utilise dans la boucle avant de l'incrémenter et il traitera toutes les dates, y compris la dernière date de enddate d'où

, Donc la réponse ci-dessus est correcte.

while (startdate <= enddate)
{
    // do something with the startdate
    startdate = startdate.adddays(interval);
}
0
répondu Robert Peter Bronstein 2015-08-03 03:40:56

Vous pouvez utiliser ceci.

 DateTime dt0 = new DateTime(2009, 3, 10);
 DateTime dt1 = new DateTime(2009, 3, 26);

 for (; dt0.Date <= dt1.Date; dt0=dt0.AddDays(3))
 {
    //Console.WriteLine(dt0.Date.ToString("yyyy-MM-dd"));
    //take action
 }
0
répondu porya ras 2018-03-27 20:22:51

Itérer toutes les 15 minutes

DateTime startDate = DateTime.Parse("2018-06-24 06:00");
        DateTime endDate = DateTime.Parse("2018-06-24 11:45");

        while (startDate.AddMinutes(15) <= endDate)
        {

            Console.WriteLine(startDate.ToString("yyyy-MM-dd HH:mm"));
            startDate = startDate.AddMinutes(15);
        }
0
répondu McNiel Viray 2018-08-06 07:59:48