Je ne sais même pas comment faire cela sans utiliser une solution horrible de type boucle / compteur. Voici le problème:
On me donne deux dates, une date de début et une date de fin et à 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 26/03/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 les dates suivantes:
13/03/2009 16/03/2009 19/03/2009 22/03/2009 25/03/2009
Alors comment diable pourrais-je faire 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?
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; }
Ensuite, vous pouvez l'utiliser comme ceci:
foreach (DateTime day in EachDay(StartDate, EndDate)) // print it or whatever
De cette manière, vous pouvez frapper tous les deux jours, tous les trois jours, uniquement les jours de la semaine, etc. Par exemple, pour revenir tous les trois jours en commençant par la date de «début», vous pouvez simplement appeler
AddDays(3)
dans la boucle au lieu deAddDays(1)
.la source
J'ai une
Range
classe 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 non vouloir exclure la fin - j'ai juste pensé que je le donnerais à titre d'exemple.)
Il s'agit essentiellement d'une forme prête à l'emploi (et plus polyvalente) de la solution de mquander.
la source
ExcludeEnd()
est mignon.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); }
la source
Code de @mquander et @Yogurt The Wise 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); }
la source
EachDayTo
etEachMonthTo
? Je pense que j'ai raté quelque chose ici.1 an plus tard, que cela aide quelqu'un,
Cette version inclut un prédicat , pour être plus flexible.
Usage
var today = DateTime.UtcNow; var birthday = new DateTime(2018, 01, 01);
Tous les jours jusqu'à mon anniversaire
var toBirthday = today.RangeTo(birthday);
Chaque mois jusqu'à mon anniversaire, étape 2 mois
var toBirthday = today.RangeTo(birthday, x => x.AddMonths(2));
Chaque année jusqu'à mon anniversaire
var toBirthday = today.RangeTo(birthday, x => x.AddYears(1));
Utilisez
RangeFrom
plutôt// same result var fromToday = birthday.RangeFrom(today); var toBirthday = today.RangeTo(birthday);
la mise en oeuvre
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); } }
Suppléments
Vous pouvez lancer une exception si le
fromDate > toDate
, mais je préfère renvoyer une plage vide à la place[]
la source
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)) { }
la source
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 }
la source
while
exécution.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......
la source
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); }
la source
Vous pourriez envisager d'écrire un itérateur à la place, ce qui vous permet d'utiliser une syntaxe de boucle 'for' normale comme '++'. J'ai recherché et trouvé une question similaire répondue ici sur StackOverflow qui donne des pointeurs pour rendre DateTime itérable.
la source
Vous pouvez utiliser la
DateTime.AddDays()
fonction pour ajouter votreDayInterval
àStartDate
et vérifier qu'il est inférieur àEndDate
.la source
il faut faire attention ici à ne pas manquer les dates où dans la boucle une meilleure solution serait.
cela vous donne la première date de date de début et de l'utiliser dans la boucle avant de l'incrémenter et il traitera toutes les dates, y compris la dernière date de fin, donc <= date de fin.
donc la réponse ci-dessus est la bonne.
while (startdate <= enddate) { // do something with the startdate startdate = startdate.adddays(interval); }
la source
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 }
la source
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); }
la source
@ jacob-sobus et @mquander et @Yogurt ne sont pas tout à fait corrects .. Si j'ai besoin du lendemain, j'attends la plupart du temps 00:00
public static IEnumerable<DateTime> EachDay(DateTime from, DateTime thru) { for (var day = from.Date; day.Date <= thru.Date; day = day.NextDay()) yield return day; } public static IEnumerable<DateTime> EachMonth(DateTime from, DateTime thru) { for (var month = from.Date; month.Date <= thru.Date || month.Year == thru.Year && month.Month == thru.Month; month = month.NextMonth()) yield return month; } public static IEnumerable<DateTime> EachYear(DateTime from, DateTime thru) { for (var year = from.Date; year.Date <= thru.Date || year.Year == thru.Year; year = year.NextYear()) yield return year; } public static DateTime NextDay(this DateTime date) { return date.AddTicks(TimeSpan.TicksPerDay - date.TimeOfDay.Ticks); } public static DateTime NextMonth(this DateTime date) { return date.AddTicks(TimeSpan.TicksPerDay * DateTime.DaysInMonth(date.Year, date.Month) - (date.TimeOfDay.Ticks + TimeSpan.TicksPerDay * (date.Day - 1))); } public static DateTime NextYear(this DateTime date) { var yearTicks = (new DateTime(date.Year + 1, 1, 1) - new DateTime(date.Year, 1, 1)).Ticks; var ticks = (date - new DateTime(date.Year, 1, 1)).Ticks; return date.AddTicks(yearTicks - ticks); } 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); } public static IEnumerable<DateTime> EachYearTo(this DateTime dateFrom, DateTime dateTo) { return EachYear(dateFrom, dateTo); }
la source
Voici mes 2 cents en 2020.
Enumerable.Range(0, (endDate - startDate).Days + 1) .ToList() .Select(a => startDate.AddDays(a));
la source