2010-07-12 9 views
60

Tengo dos DateTime s, y quiero obtener todos los DateTime s entre estas Fechas. Por ejemplo, si mis fechas son como 01.01.2010 - 05.01.2010, mi función debe devolverme una lista de fecha (Lista), y debe contener 01.01.2010, 02.01.2010, 03.01.2010, 04.01.2010, y 05.01.2010.Obteniendo todos los DateTimes entre dos 'DateTime's en C#

Escribí una función como esta. Funciona bien, si mis fechas son en un mes. No funcionará si mis fechas son como 01.01.2010 - 05.02.2010. Porque el mes cambió y mi función no puede manejarlo. ¿Hay alguna función en C# que devuelva todas las fechas entre dos fechas? ¿O cómo puedo manejar el cambio de mes?

public void GetAllDatesAndInitializeTickets(DateTime startingDate, DateTime endingDate) 
    { 
     List<DateTime> allDates = new List<DateTime>(); 

     int starting = startingDate.Day; 
     int ending = endingDate.Day; 

     for (int i = starting; i <= ending; i++) 
     { 
      allDates.Add(new DateTime(startingDate.Year, startingDate.Month, i)); 
     } 

Pregunta resuelto, ver respuesta simple de Tim Robinson de usar.

Respuesta

115

Puede usar los objetos DateTime directamente en el bucle, en lugar de su int. DateTime.AddDays maneja el mes finaliza correctamente.

for (DateTime date = startingDate; date <= endingDate; date = date.AddDays(1)) 
    allDates.Add(date); 
7
public IEnumerable<DateTime> GetAllDatesAndInitializeTickets(DateTime startingDate, DateTime endingDate) 
{ 
    if (endingDate < startingDate) 
    { 
     throw new ArgumentException("endingDate should be after startingDate"); 
    } 
    var ts = endingDate - startingDate; 
    for (int i = 0; i < ts.TotalDays; i++) 
    { 
     yield return startingDate.AddDays(i); 
    } 
} 
+0

Niza uso de rendimiento, la debería haber pensado en eso. – Jamiec

3

estabas tan cerca ... simplemente no usar el día, usar todo el día.

static IEnumerable<DateTime> GetAllDatesAndInitializeTickets(DateTime startingDate, DateTime endingDate) 
{ 
    List<DateTime> allDates = new List<DateTime>(); 


    for (DateTime i = startingDate; i <= endingDate; i = i.AddDays(1)) 
    { 
     allDates.Add(i); 
    } 
    return allDates.AsReadOnly(); 
} 
+1

+1 para '.AsReadOnly();'. – Odys

52

¿Qué tal algo así?

public IEnumerable<DateTime> DateRange(DateTime fromDate, DateTime toDate) 
{ 
    return Enumerable.Range(0, toDate.Subtract(fromDate).Days + 1) 
        .Select(d => fromDate.AddDays(d)); 
} 

Editar: Probado ahora. :)

+0

Justo lo que necesitaba. Funciona y está realmente limpio. – gligoran

1

Aquí es una aplicación de consola rápida para demostrar cómo hacerlo - AddDays() utilizar en su lugar:

class Program 
{ 
    static void Main(string[] args) 
    { 

     GetDates(new DateTime(2010, 1, 1), new DateTime(2010, 2, 5)); 

     Console.ReadKey(); 
    } 

    static List<DateTime> GetDates(DateTime startDate, DateTime endDate) 
    { 
     List<DateTime> dates = new List<DateTime>(); 

     while ((startDate = startDate.AddDays(1)) < endDate) 
     { 
      dates.Add(startDate); 
     } 

     return dates; 
    } 
} 
+0

Maldita sea, muchas respuestas a esta. – slugster

1

dado un valor lowerdate y más alto valor de fecha en cadena y una frecuencia como tercer parámetro de este método debe devolver un diccionario de fechas; donde la clave es el valor inicial de un rango de fechas y el valor es el rango respectivo. Esto funciona bien si la frecuencia es semanal o mensual; puede personalizarla según sus necesidades. Los valores de fecha que se pasen deberían estar en el formato correcto o podría necesitar formatearlo usando tryParseExact o algo así.

protected static Dictionary<DateTime, String> getDateRange(String lowerDate, String higherDate, String frequency) 
    { 
     DateTime startDate, endDate; 
     startDate = Convert.ToDateTime(lowerDate); 
     endDate = Convert.ToDateTime(higherDate); 

     Dictionary<DateTime, String> returnDict = new Dictionary<DateTime, String>(); 

     while (frequency.Equals("weekly") ? (startDate.AddDays(7) <= endDate) : (startDate.AddMonths(1) <= endDate)) 
     { 
      if (frequency.Equals("weekly")) 
      { 
       returnDict.Add(startDate, startDate + "-" + startDate.AddDays(7)); 
       startDate = startDate.AddDays(8); 
      } 
      if (frequency.Equals("monthly")) 
      { 
       returnDict.Add(startDate, startDate + "-" + startDate.AddMonths(1)); 
       startDate = startDate.AddMonths(1).AddDays(1); 
      } 
     } 

     returnDict.Add(startDate, startDate + "-" + endDate); 

     return returnDict; 
    } 
+0

Formatee el código para que la primera línea de la función también tenga el formato de código. Esta respuesta no resuelve la pregunta, ya que él escribe que ya tiene dos DateTimes y quiere una lista, pero su función toma cadenas en lugar de DateTimes y devuelve un diccionario en lugar de una lista. Además, quiere que cada fecha entre las fechas de inicio y finalización, no solo una vez a la semana o una vez al mes. – tomsv

1

Las soluciones superiores fallarán si la fecha incluye horas diferentes. Aquí es una solución de conseguir todas las horas y todos los días:

Todos los Días:

static public List<string> get_days_between_two_dates(DateTime start_date, DateTime end_date) 
    { 
     List<string> days_list = new List<string>(); 
     DateTime temp_start; 
     DateTime temp_end; 

     //--Normalize dates by getting rid of minues since they will get in the way when doing the loop 
     temp_start = new DateTime(start_date.Year, start_date.Month, start_date.Day); 
     temp_end = new DateTime(end_date.Year, end_date.Month, end_date.Day); 

     //--Example Should return 
     //--1-12-2014 5:59AM - 1-13-2014 6:01AM return 12 and 13 
     for (DateTime date = temp_start; date <= temp_end; date = date.AddDays(1)) 
     { 
      days_list.Add(date.ToShortDateString()); 
     } 

     return days_list; 
    } 

Todos Horas:

static public List<string> get_hours_between_two_dates(DateTime start_date, DateTime end_date) 
    { 
     List<string> hours_24_list = new List<string>(); 
     DateTime temp_start; 
     DateTime temp_end; 

     //--Normalize dates by getting rid of minutes since they will get in the way when doing the loop 
     temp_start = new DateTime(start_date.Year, start_date.Month, start_date.Day, start_date.Hour, 0, 0); 
     temp_end = new DateTime(end_date.Year, end_date.Month, end_date.Day, end_date.Hour, 0, 0); 

     //--Example Should return 
     //--5:59AM - 6:01AM return 5am and 6am 
     for (DateTime date = temp_start; date <= temp_end; date = date.AddHours(1)) 
     { 
      hours_24_list.Add(date.ToShortTimeString()); 
     } 

     return hours_24_list; 
    } 
0
static IEnumerable<DateTime> GetAllDatesAndInitializeTickets(DateTime startingDate, DateTime endingDate) 
{ 
    List<DateTime> allDates = new List<DateTime>(); 


    for (DateTime i = startingDate; i <= endingDate; i = i.AddDays(1)) 
    { 
     allDates.Add(i); 
    } 
    return allDates.AsReadOnly(); 
} 
Cuestiones relacionadas