entre - rango de fechas c#
¿Cómo recorro un rango de fechas? (13)
1 año después, puede ayudar a alguien,
Esta versión incluye un predicado , para ser más flexible.
Uso
var today = DateTime.UtcNow;
var birthday = new DateTime(2018, 01, 01);
Diariamente a mi cumpleaños
var toBirthday = today.RangeTo(birthday);
Mensualmente a mi cumpleaños, Paso 2 meses
var toBirthday = today.RangeTo(birthday, x => x.AddMonths(2));
Anualmente a mi cumpleaños
var toBirthday = today.RangeTo(birthday, x => x.AddYears(1));
Use RangeFrom
en RangeFrom
lugar
// same result
var fromToday = birthday.RangeFrom(today);
var toBirthday = today.RangeTo(birthday);
Implementación
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
Podría lanzar una excepción si fromDate > toDate
, pero prefiero devolver un intervalo vacío []
Ni siquiera estoy seguro de cómo hacer esto sin utilizar alguna solución de tipo loop / counter horrible. Aquí está el problema:
Me dieron dos fechas, una fecha de inicio y una fecha de finalización y en un intervalo específico necesito tomar alguna medida. Por ejemplo: para cada fecha entre el 3/10/2009 cada tres días hasta el 3/26/2009, necesito crear una entrada en una lista. Entonces mis entradas serían:
DateTime StartDate = "3/10/2009";
DateTime EndDate = "3/26/2009";
int DayInterval = 3;
y mi salida sería una lista que tiene las siguientes fechas:
13/03/2009 16/03/2009 19/03/2009 22/03/2009 25/03/2009
Entonces, ¿cómo diablos iba a hacer algo como esto? Pensé en usar un bucle for que iteraría entre todos los días en el rango con un contador separado como ese:
int count = 0;
for(int i = 0; i < n; i++)
{
count++;
if(count >= DayInterval)
{
//take action
count = 0;
}
}
Pero parece que podría haber una mejor manera?
Bueno, deberás pasar por encima de ellos de una forma u otra. Prefiero definir un método como este:
public IEnumerable<DateTime> EachDay(DateTime from, DateTime thru)
{
for(var day = from.Date; day.Date <= thru.Date; day = day.AddDays(1))
yield return day;
}
Entonces puedes usarlo así:
foreach (DateTime day in EachDay(StartDate, EndDate))
// print it or whatever
De esta manera, puede pulsar día por medio, cada tres días, solo los días de la semana, etc. Por ejemplo, para volver cada tres días a partir de la fecha de inicio, simplemente puede llamar AddDays(3)
en el bucle en lugar de AddDays(1)
.
Código de @mquander y @Yogurt The Wise utilizado en extensiones:
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);
}
De acuerdo con el problema, puedes probar esto ...
// looping between date range
while (startDate <= endDate)
{
//here will be your code block...
startDate = startDate.AddDays(1);
}
Gracias......
Para su ejemplo, puede intentarlo
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);
}
Puede considerar escribir un iterador en su lugar, lo que le permite usar la sintaxis de bucle ''para'' normal como ''++''. Busqué y encontré una pregunta similar answered aquí en que da sugerencias para hacer iterable DateTime.
Puede usar la función DateTime.AddDays()
para agregar su DayInterval
a StartDate
y verificar que sea menor que EndDate
.
Tengo una clase Range
en MiscUtil que podría MiscUtil útil. Combinado con los diversos métodos de extensión, podría hacer:
foreach (DateTime date in StartDate.To(EndDate).ExcludeEnd()
.Step(DayInterval.Days())
{
// Do something with the date
}
(Puede o no querer excluir el final, solo pensé en proporcionarlo como ejemplo).
Esto es básicamente una forma de solución de mquander lista para rodar (y más general).
puedes usar esto
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
}
tienes que tener cuidado aquí para no perderte las fechas en las que una mejor solución sería.
esto le da la primera fecha de inicio y la usa en el ciclo antes de incrementarla y procesará todas las fechas, incluida la última fecha de enddate, por lo tanto, <= enddate.
entonces la respuesta anterior es la correcta.
while (startdate <= enddate)
{
// do something with the startdate
startdate = startdate.adddays(interval);
}
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);
}
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))
{
}
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
}