मैं एक तिथि सीमा के माध्यम से कैसे लूप कर सकता हूं?


197

मुझे यह भी पता नहीं है कि लूप / काउंटर प्रकार के समाधान के लिए कुछ भयानक उपयोग किए बिना यह कैसे करना है। यहाँ समस्या है:

मुझे दो तिथियां, एक आरंभ तिथि और एक अंतिम तिथि दी गई है और एक निर्दिष्ट अंतराल पर मुझे कुछ कार्रवाई करने की आवश्यकता है। उदाहरण के लिए: प्रत्येक तीसरे दिन 3/10-2009 के बीच की तारीख 3/26-2009 तक मुझे सूची में प्रविष्टि बनाने की आवश्यकता है। तो मेरे इनपुट होंगे:

DateTime StartDate = "3/10/2009";
DateTime EndDate = "3/26/2009";
int DayInterval = 3;

और मेरा आउटपुट एक सूची होगी जिसमें निम्नलिखित तारीखें होंगी:

3/13/2009 3/16/2009 3/19/2009 3/22/2009 3/25/2009

तो हेक मैं ऐसा कुछ कैसे करूंगा? मैंने एक लूप का उपयोग करने के बारे में सोचा जो हर दिन इस तरह से एक अलग काउंटर के साथ रेंज में पुनरावृति करेगा:

int count = 0;

for(int i = 0; i < n; i++)
{
     count++;
     if(count >= DayInterval)
     {
          //take action
          count = 0;
     }

}

लेकिन ऐसा लगता है कि एक बेहतर तरीका हो सकता है?


1
मुझे लगता है कि C # में डेट्स के लिए डेटा स्ट्रक्चर होता है, जिसका आप इस्तेमाल कर सकते हैं।
अन्ना

जवाबों:


470

ठीक है, आपको एक या दूसरे तरीके से उन पर लूप करना होगा। मैं इस तरह से एक विधि को परिभाषित करना पसंद करता हूं:

public IEnumerable<DateTime> EachDay(DateTime from, DateTime thru)
{
    for(var day = from.Date; day.Date <= thru.Date; day = day.AddDays(1))
        yield return day;
}

तो आप इसे इस तरह से उपयोग कर सकते हैं:

foreach (DateTime day in EachDay(StartDate, EndDate))
    // print it or whatever

इस तरीके से आप हर दूसरे दिन, हर तीसरे दिन, केवल सप्ताह के दिनों इत्यादि को हिट कर सकते हैं। उदाहरण के लिए, "स्टार्ट" तारीख से शुरू होने वाले हर तीसरे दिन को वापस करने के लिए, आप AddDays(3)इसके बजाय लूप में कॉल कर सकते हैं AddDays(1)


18
तुम भी अंतराल के लिए एक और पैरामीटर जोड़ सकते हैं।
जस्टिन ड्र्यू डे

यह पहली तारीख को शामिल किया जाएगा। यदि आप ऐसा नहीं चाहते हैं, तो बस 'var day = from.Date' से 'var day = from' तक बदलें ।ate.AddDays (dayInterval) '
SwDevMan81

3
एक दिलचस्प और वास्तविक शब्द समस्या के लिए एक बहुत अच्छा समाधान। मुझे पसंद है कि यह भाषा की कुछ उपयोगी तकनीकों को कैसे दिखाता है। और यह मुझे याद दिलाता है कि लूप के लिए ही नहीं है (int i = 0; ...) - (-।
ऑडियोस

9
इस विस्तार को डेटाइम करने के लिए इसे और बेहतर बनाया जा सकता है।
मैट

1
दिनों और महीनों के विस्तार के लिए मेरा जवाब देखें;) बस अपनी खुशी के लिए: D
जैकब सोबस

31

मेरे पास MiscUtilRange में एक क्लास है जिसे आप उपयोगी पा सकते हैं। विभिन्न विस्तार विधियों के साथ संयुक्त, आप कर सकते हैं:

foreach (DateTime date in StartDate.To(EndDate).ExcludeEnd()
                                   .Step(DayInterval.Days())
{
    // Do something with the date
}

(आप अंत को बाहर करना चाहते हैं या नहीं कर सकते हैं - मुझे लगा कि मैं इसे एक उदाहरण के रूप में प्रदान करूंगा।)

यह मूल रूप से mquander के समाधान का एक तैयार-लुढ़का (और अधिक सामान्य-उद्देश्य) रूप है।


2
निश्चित रूप से सिर्फ स्वाद की बात है कि आप ऐसी चीजों को पसंद करते हैं जो विस्तार के तरीके हैं या नहीं। ExcludeEnd()प्यारा है।
mqp

बेशक, आप विस्तार विधियों का उपयोग किए बिना वह सब कर सकते हैं। यह IMO :) पढ़ने के लिए बहुत ही बदसूरत और कठिन हो जाएगा :)
जॉन स्कीट

1
वाह - क्या एक महान संसाधन MiscUtil है - आपके उत्तर के लिए धन्यवाद!
वनकिडनी

1
किसी और के मामले में, लेकिन मुझे एक संरचना / वर्ग के रूप में DayInterval गलत लगा, यह वास्तव में इस नमूने में एक पूर्णांक है। यह निश्चित रूप से स्पष्ट है यदि आप प्रश्न को ध्यान से पढ़ते हैं, जो मैंने नहीं किया।
15

23

अपने उदाहरण के लिए आप कोशिश कर सकते हैं

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

1
यह वही बात है जो मैं सोच रहा था (हालाँकि मुझे ऊपर वाले का जवाब भी पसंद है), लेकिन मैं यह पता नहीं लगा सकता कि आपको इतनी जल्दी एक अच्छा कोड नमूना कैसे मिला!
TLiebe

3
मुझे लगता है कि हमें StartDate.AddDays (DayInterval) की आवश्यकता है; एक बार इस पाश में दो बार नहीं।
अब्दुल सबूर

15

एक्सटेंशन में उपयोग किए गए @mquander और @Yogurt से कोड:

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

का फ़ायदा क्या है EachDayToऔर EachMonthTo? मुझे लगता है कि मुझे यहां कुछ याद आया।
एलिसन

@ एलिसन वे हैं जो डेटफ़ॉर्म ऑब्जेक्ट पर काम करने वाले विस्तार के तरीके हैं :) तो आप उन्हें पहले से बनाई गई डेटाइम ऑब्जेक्ट्स पर अधिक धाराप्रवाह (केवल उदाहरण के बाद का उपयोग करके) उपयोग कर सकते हैं। यहां विस्तार के तरीकों के बारे में अधिक जानकारी: docs.microsoft.com/en-us/dotnet/csharp/programming-guide/…
याकूब

8
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))
{

}

8

1 साल बाद, यह किसी की मदद कर सकता है,

इस संस्करण में एक विधेय शामिल है अधिक लचीला होने के लिए ।

प्रयोग

var today = DateTime.UtcNow;
var birthday = new DateTime(2018, 01, 01);

मेरे जन्मदिन पर दैनिक

var toBirthday = today.RangeTo(birthday);  

मेरे जन्मदिन के लिए मासिक, चरण 2 महीने

var toBirthday = today.RangeTo(birthday, x => x.AddMonths(2));

वार्षिक रूप से मेरे जन्मदिन पर

var toBirthday = today.RangeTo(birthday, x => x.AddYears(1));

RangeFromइसके बजाय उपयोग करें

// same result
var fromToday = birthday.RangeFrom(today);
var toBirthday = today.RangeTo(birthday);

कार्यान्वयन

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

अतिरिक्त

यदि आप अपवाद को फेंक सकते हैं fromDate > toDate, लेकिन मैं इसके बजाय एक खाली सीमा वापस करना पसंद करता हूं[]


वाह - यह वास्तव में व्यापक है। धन्यवाद अहमद!
वनकिडनी

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

ध्यान दें कि इसमें शुरुआत की तारीख शामिल नहीं है, क्योंकि यह एक दिन पहली बार whileरन जोड़ता है ।
जॉन वॉशम

2

समस्या के अनुसार आप यह कोशिश कर सकते हैं ...

// looping between date range    
while (startDate <= endDate)
{
    //here will be your code block...

    startDate = startDate.AddDays(1);
}

धन्यवाद......


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

1

आप इसके बजाय एक इटरेटर लिखने पर विचार कर सकते हैं, जो आपको '++' जैसे लूप सिंटैक्स के लिए सामान्य का उपयोग करने की अनुमति देता है। मैंने StackOverflow पर उत्तर दिया गया ऐसा ही एक प्रश्न खोजा और पाया, जो DateTime को चलने योग्य बनाने पर संकेत देता है।


1

आप उपयोग कर सकते हैं DateTime.AddDays()अपने को जोड़ने के लिए समारोह DayIntervalके लिए StartDateऔर इसे से भी कम है जांच लें EndDate


0

आपको यहाँ सावधान रहना होगा कि तारीखों को याद न करें जब लूप में बेहतर समाधान होगा।

यह आपको शुरुआत की पहली तारीख देता है और इसे बढ़ाने से पहले लूप में उपयोग करता है और यह अंतिम तिथि सहित सभी तिथियों को प्रोसेस करेगा इसलिए <= एंडडेट करें।

इसलिए उपरोक्त उत्तर सही है।

while (startdate <= enddate)
{
    // do something with the startdate
    startdate = startdate.adddays(interval);
}

0

आप इसका उपयोग कर सकते हैं।

 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
 }

यह वास्तव में पर्याप्त है। अच्छा!
वनकिडनी

0

हर 15 मिनट में Iterate करें

DateTime startDate = DateTime.Parse("2018-06-24 06:00");
        DateTime endDate = DateTime.Parse("2018-06-24 11:45");

        while (startDate.AddMinutes(15) <= endDate)
        {

            Console.WriteLine(startDate.ToString("yyyy-MM-dd HH:mm"));
            startDate = startDate.AddMinutes(15);
        }

0

@ जकोब-सोबस और @ म्कैंडर और @ योगर्ट बिल्कुल सही नहीं है .. अगर मुझे अगले दिन की जरूरत है तो मैं ज्यादातर 00:00 तक इंतजार करूंगा।

    public static IEnumerable<DateTime> EachDay(DateTime from, DateTime thru)
    {
        for (var day = from.Date; day.Date <= thru.Date; day = day.NextDay())
            yield return day;
    }

    public static IEnumerable<DateTime> EachMonth(DateTime from, DateTime thru)
    {
        for (var month = from.Date; month.Date <= thru.Date || month.Year == thru.Year && month.Month == thru.Month; month = month.NextMonth())
            yield return month;
    }

    public static IEnumerable<DateTime> EachYear(DateTime from, DateTime thru)
    {
        for (var year = from.Date; year.Date <= thru.Date || year.Year == thru.Year; year = year.NextYear())
            yield return year;
    }

    public static DateTime NextDay(this DateTime date)
    {
        return date.AddTicks(TimeSpan.TicksPerDay - date.TimeOfDay.Ticks);
    }

    public static DateTime NextMonth(this DateTime date)
    {
        return date.AddTicks(TimeSpan.TicksPerDay * DateTime.DaysInMonth(date.Year, date.Month) - (date.TimeOfDay.Ticks + TimeSpan.TicksPerDay * (date.Day - 1)));
    }

    public static DateTime NextYear(this DateTime date)
    {
        var yearTicks = (new DateTime(date.Year + 1, 1, 1) - new DateTime(date.Year, 1, 1)).Ticks;
        var ticks = (date - new DateTime(date.Year, 1, 1)).Ticks;
        return date.AddTicks(yearTicks - ticks);
    }

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

    public static IEnumerable<DateTime> EachYearTo(this DateTime dateFrom, DateTime dateTo)
    {
        return EachYear(dateFrom, dateTo);
    }

0

यहाँ 2020 में मेरे 2 सेंट हैं।

Enumerable.Range(0, (endDate - startDate).Days + 1)
.ToList()
.Select(a => startDate.AddDays(a));

यह कमाल का है। 👍
onekidney
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.