Comment faire une boucle sur une plage de dates?

Je ne suis même pas sûr de savoir comment faire cela sans utiliser un horrible pour la 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 et le 3/26/2009, je dois créer une entrée dans une liste. Donc mes intrants seraient:

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

et ma sortie serait une liste qui a les dates suivantes:

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 effectuait une itération entre chaque jour de la plage avec un compteur distinct comme celui-ci:

 int count = 0; for(int i = 0; i = DayInterval) { //take action count = 0; } } 

Mais il semble y avoir un meilleur moyen?

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 EachDay(DateTime from, DateTime thru) { for(var day = from.Date; day.Date <= thru.Date; day = day.AddDays(1)) yield return day; } 

Ensuite, vous pouvez l'utiliser comme ceci:

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

De cette manière, vous pouvez atteindre tous les deux jours, tous les trois jours, seulement les jours de la semaine, etc. Par exemple, pour retourner tous les trois jours à partir de la date de début, vous pouvez simplement appeler AddDays(3) AddDays(1) .

J’ai une classe Range dans MiscUtil que vous pourriez trouver utile. Combiné aux 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 non ne pas vouloir exclure la fin – je pensais juste que je fournirais cet exemple.)

Ceci est essentiellement une forme de solution de mquander prête à l’emploi (et plus générale).

Pour votre exemple, vous pouvez essayer

 DateTime StartDate = new DateTime(2009, 3, 10); DateTime EndDate = new DateTime(2009, 3, 26); int DayInterval = 3; List dateList = new List(); while (StartDate.AddDays(DayInterval) <= EndDate) { StartDate = StartDate.AddDays(DayInterval); dateList.Add(StartDate); } 

Code de @mquander et @Yogurt The Wise utilisé dans les extensions:

 public static IEnumerable EachDay(DateTime from, DateTime thru) { for (var day = from.Date; day.Date <= thru.Date; day = day.AddDays(1)) yield return day; } public static IEnumerable 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 EachDayTo(this DateTime dateFrom, DateTime dateTo) { return EachDay(dateFrom, dateTo); } public static IEnumerable EachMonthTo(this DateTime dateFrom, DateTime dateTo) { return EachMonth(dateFrom, dateTo); } 
 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)) { } 

1 an plus tard, peut-il aider quelqu’un,

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

Usage

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

Quotidien à mon anniversaire

 var toBirthday = today.RangeTo(birthday); 

Mensuel à mon anniversaire, étape 2 mois

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

Annuellement à mon anniversaire

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

Utilisez plutôt RangeFrom

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

la mise en oeuvre

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

Extras

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

 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 } 

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......

Vous pourriez envisager d’écrire un iterator à la place, ce qui vous permet d’utiliser une syntaxe de boucle normale “pour” comme “++”. J’ai cherché et trouvé une question similaire à la réponse ici sur StackOverflow qui donne des indications sur le fait de rendre DateTime itérable.

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

 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); } 

Il faut faire attention à ne pas rater les dates quand une solution serait dans la boucle.

cela vous donne la première date de startdate et l’utilise dans la boucle avant de l’incrémenter et cela traitera toutes les dates, y compris la dernière date de fin, donc <= enddate.

donc la réponse ci-dessus est la bonne.

 while (startdate <= enddate) { // do something with the startdate startdate = startdate.adddays(interval); } 

vous pouvez l’utiliser.

  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 } 

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); }