Abrufen aller DateTimes zwischen zwei 'DateTimes' in C #

76

Ich habe zwei DateTimes, und ich möchte alle DateTimes zwischen diesen Daten bekommen. Wenn meine Daten beispielsweise 01.01.2010 - 05.01.2010 sind, sollte meine Funktion mir eine Datumsliste (Liste) zurückgeben, die 01.01.2010, 02.01.2010, 03.01.2010, 04.01.2010 und enthalten muss 05.01.2010.

Ich habe eine solche Funktion geschrieben. Es funktioniert gut, wenn meine Daten in einem Monat sind. Es wird nicht funktionieren, wenn meine Daten vom 01.01.2010 - 05.02.2010 sind. Weil sich der Monat geändert hat und meine Funktion damit nicht umgehen kann. Gibt es in C # eine Funktion, die alle Daten zwischen zwei Daten zurückgibt? Oder wie kann ich mit Monatsänderungen umgehen?

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

Frage gelöst, siehe Tim Robinsons einfache Antwort.

Serkan Hekimoglu
quelle

Antworten:

133

Sie können DateTimeObjekte direkt in der Schleife anstelle von Ihren verwenden int. DateTime.AddDaysbehandelt Monatsenden korrekt.

for (DateTime date = startingDate; date <= endingDate; date = date.AddDays(1))
    allDates.Add(date);
Tim Robinson
quelle
74

Wie wäre es mit so etwas?

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

Bearbeiten: Jetzt getestet. :) :)

Matt Hamilton
quelle
Genau das, was ich brauchte. Funktioniert und ist wirklich sauber.
Gligoran
9
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);
    }
}
Darin Dimitrov
quelle
Gute Verwendung der Ausbeute, sollte man sich vorstellen.
Jamiec
4

Du warst so nah dran ... benutze einfach nicht den Tag, sondern das ganze Datum.

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();
}
Jamiec
quelle
1

Hier ist eine schnelle Konsolen-App, die zeigt, wie es geht - verwenden Sie AddDays()stattdessen:

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;
    }
}
Slugster
quelle
Verdammt, viele Antworten auf diese Frage.
Slugster
1

Bei einem niedrigeren Datumswert und einem höheren Datumswert in String und einer Häufigkeit als drittem Parameter sollte diese Methode ein Datumswörterbuch zurückgeben. Dabei ist der Schlüssel der Startwert eines Datumsbereichs und der Wert der jeweilige Bereich. Dies funktioniert einwandfrei, wenn die Häufigkeit entweder wöchentlich oder monatlich ist. Sie können sie nach Ihren Wünschen anpassen. Die übergebenen Datumswerte sollten im richtigen Format vorliegen, oder Sie müssen sie möglicherweise mit tryParseExact oder ähnlichem formatieren.

    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;
    }
Shibasis Sengupta
quelle
Bitte formatieren Sie den Code so, dass die erste Zeile der Funktion auch als Code formatiert wird. Diese Antwort löst die Frage nicht, da er schreibt, dass er bereits zwei DateTimes hat und eine Liste möchte, Ihre Funktion jedoch Zeichenfolgen anstelle von DateTimes verwendet und ein Wörterbuch anstelle einer Liste zurückgibt. Außerdem möchte er jedes Datum zwischen dem Start- und dem Enddatum, nicht nur einmal pro Woche oder einmal im Monat.
Tomsv
1

Die Top-Lösungen schlagen fehl, wenn das Datum unterschiedliche Stunden enthält. Hier ist eine Lösung, die alle Stunden und alle Tage erfasst:

Alle Tage:

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

Alle Stunden:

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;
    }
timi2shoes
quelle
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();
}
user788592
quelle