Je ne sais même pas comment faire cela sans utiliser une solution horrible pour le 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 et 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:
3/13/2009 3/16/2009 3/19/2009 3/22/2009 3/25/2009
Alors, comment pourrais-je faire quelque chose comme ça? J'ai pensé à utiliser une boucle for qui itérerait chaque jour de 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?
Eh bien, vous devrez les survoler 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 toucher 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 de AddDays(1)
.
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 non vouloir exclure la fin - je pensais juste que je donnerais cela à titre d'exemple)
Ceci est fondamentalement une forme prête à l'emploi (et plus polyvalente) de la solution de mquander.
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);
}
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);
}
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, que cela aide quelqu'un,
Cette version inclut un predicate, pour être plus flexible.
var today = DateTime.UtcNow;
var birthday = new DateTime(2018, 01, 01);
var toBirthday = today.RangeTo(birthday);
var toBirthday = today.RangeTo(birthday, x => x.AddMonths(2));
var toBirthday = today.RangeTo(birthday, x => x.AddYears(1));
RangeFrom
à la place// same result
var fromToday = birthday.RangeFrom(today);
var toBirthday = today.RangeTo(birthday);
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);
}
}
Vous pouvez lancer une exception si le 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
}
Vous pouvez envisager d'écrire un itérateur à la place, ce qui vous permet d'utiliser une syntaxe de boucle "pour" telle que "++". J'ai cherché et trouvé une question similaire répondu ici sur StackOverflow qui donne des indications pour rendre DateTime itérable.
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 pouvez utiliser la fonction DateTime.AddDays()
pour ajouter votre DayInterval
à la StartDate
et vous assurer qu'elle est inférieure à la 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);
}
vous devez faire attention ici pour ne pas manquer les dates où une meilleure solution serait dans la boucle.
cela vous donne la première date de date de début et 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.
la réponse ci-dessus est donc 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
}
@ jacob-sobus et @mquander et @Yogurt pas tout à fait correct .. Si j'ai besoin du lendemain, j'attends surtout 00:00 heure
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);
}
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);
}