Отримання всіх DateTimes між двома 'DateTime's в C #


77

У мене є два DateTimes, і я хочу отримати всі DateTimes між цими датами. Наприклад, якщо мої дати схожі на 01.01.2010 - 05.01.2010, моя функція повинна повернути мені список дат (Список), і він повинен містити 01.01.2010, 02.01.2010, 03.01.2010, 04.01.2010 та 05.01.2010.

Я написав таку функцію. Це чудово працює, якщо мої дати через місяць. Це не спрацює, якщо мої дати будуть як 01.01.2010 - 05.02.2010. Оскільки місяць змінився, і моя функція не справляється з цим. Чи є в C # функція, яка повертає всі дати між двома датами? Або як я можу впоратися зі зміною місяця?

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

Питання вирішено, див. Просту відповідь у відповіді Тіма Робінсона.

Відповіді:


133

Ви можете використовувати DateTimeоб'єкти безпосередньо в циклі, замість вашого int. DateTime.AddDaysобробляє місяць закінчується правильно.

for (DateTime date = startingDate; date <= endingDate; date = date.AddDays(1))
    allDates.Add(date);

75

Як щодо чогось такого?

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

Редагувати: Перевірено зараз. :)


Якраз те, що мені було потрібно. Працює і справді чисто.
глігоран

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

Приємне використання врожаю, слід думати про це.
Jamiec

5

Ви були так близько ... просто не використовуйте день, використовуйте цілу дату.

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

Ось швидкий консольний додаток, щоб продемонструвати, як це зробити - використовуйте AddDays()замість цього:

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

1

Враховуючи значення нижчої дати та вище значення дати в рядку та частоту як третій параметр, цей метод повинен повертати словник дат; де ключ - початкове значення діапазону дат, а значення - відповідний діапазон. Це чудово працює, якщо частота буває щотижня або щомісяця - ви можете налаштувати її відповідно до своїх потреб. Передані значення дати повинні бути у відповідному форматі, або, можливо, вам доведеться відформатувати їх за допомогою tryParseExact або щось подібне.

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

Будь ласка, відформатуйте код так, щоб перший рядок функції також був відформатований як код. Ця відповідь не вирішує питання, оскільки він пише, що у нього вже є два DateTimes і хоче Список, але ваша функція бере рядки замість DateTimes і повертає словник замість списку. Крім того, він хоче, щоб кожна дата була між датою початку та закінчення, а не лише раз на тиждень або раз на місяць.
tomsv

1

Найкращі рішення не дадуть результатів, якщо дата включає різні години. Ось рішення, яке отримує всі години та всі дні:

Всі дні:

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

Усі години:

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();
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.