2010-07-12 10 views
60

Ho due DateTime s, e voglio ottenere tutti i DateTime s tra queste Date. Ad esempio, se le mie date sono come 01.01.2010 - 05.01.2010, la mia funzione dovrebbe restituirmi un elenco di date (Elenco), e deve contenere 01.01.2010, 02.01.2010, 03.01.2010, 04.01.2010, e 05.01.2010.Ottenere tutti i DateTimes tra due 'DateTime in C#

Ho scritto una funzione come questa. Funziona bene, se le mie date sono tra un mese. Non funzionerà se le mie date sono come 01.01.2010 - 05.02.2010. Perché il mese è cambiato e la mia funzione non può gestirlo. Esiste una funzione in C# che restituisce tutte le date tra due date? O come posso gestire il cambio mese?

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

Domanda risolta, vedere la semplice risposta di Tim Robinson.

risposta

115

È possibile utilizzare gli oggetti DateTime direttamente nel ciclo, al posto di int. DateTime.AddDays gestisce correttamente le scadenze del mese.

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

Nizza uso di resa, shoulda pensato. – Jamiec

3

Si erano così vicino ... basta non utilizzare il giorno, utilizzare l'intero data.

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 per '.AsReadOnly();'. – Odys

52

Che ne dici di qualcosa di simile?

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

Modifica: Testato ora. :)

+0

Proprio quello di cui avevo bisogno. Funziona ed è veramente pulito. – gligoran

1

Ecco una console app rapido per dimostrare come farlo - utilizzare AddDays() invece:

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

Dannazione, molte risposte a questo. – slugster

1

dato un valore lowerdate e più alto valore di data in stringa e una frequenza come terzo parametro questo metodo dovrebbe restituire un dizionario di date; dove la chiave è il valore iniziale di un intervallo di date e il valore è il rispettivo intervallo. Funziona bene se la frequenza è settimanale o mensile - è possibile personalizzarlo secondo le proprie necessità. I valori di data passati devono essere nel formato corretto o potrebbe essere necessario formattarlo utilizzando tryParseExact o qualcosa del genere.

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

Formattare il codice in modo che anche la prima riga della funzione sia formattata come codice. Questa risposta non risolve la domanda, dal momento che scrive che ha già due DateTimes e vuole una Lista, ma la tua funzione prende le stringhe invece di DateTimes e restituisce un Dizionario invece di una lista. Inoltre, vuole ogni data tra le date di inizio e di fine, non solo una volta alla settimana o una volta al mese. – tomsv

1

Le soluzioni migliori non funzioneranno se la data include ore diverse. Ecco una soluzione ottenere tutte le ore e tutti i giorni:

Tutti i giorni:

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

tutte le ore:

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(); 
} 
Problemi correlati