Find an algorythm to calculate weeks of a List<Datetime>

MSFanboy
MSFanboy used Ask the Experts™
on
Hello,

I am trying to find something generic without any hacks or too many checks/if`s etc.. because my solution works 99% but there are too many "exceptions" so I try to start again and find something better/more clear code.

Task:

I have a List of Datetimes selected by a user from a startdate with datepicker and a enddate from datepicker. For example user selected 01.07.2010 as startdate and as enddate 22.07.2010.

So my List of Datetimes has this: 01.07..,02.07..,03.07.,04.07..........21.07.,22.07.2010

PSEUDO-Code to give you a start help :P and to give you another HINT:

The first week object and the last week object in the final List<Week> CAN always be different from the week objects within the first AND last week object in the final List<Week>.

The problem is find something generic when you can not compute the week object with a mutual algorythm you can apply for EVERY week.

Now have fun:

var weekList = new List<Week>();
for( int i = 0; i < dateList.Count; i++) // Please do not consider the CurrentCulture because my firstDayOfWeek is ALWAYS MONDAY
{
     if(1 == (int)dateList[i].DayOfWeek) // When datetime in the dateList is a MONDAY (1)
     {
            
      }
      else // No MONDAY
       {

       }
}

[b]Week.cs:[/b]
public int WeekID {get;set;}
public List<Day> Days {get;set;}

[b]Day.cs:[/b]
public Datetime MeetingDate {get;set;}

Open in new window



Basing on my above dateList I should get this  List of Weeks as result:

Week1.Days:
01.07.2010
02.07.2010
03.07.2010
04.07.2010
Week2.Days:
05.07.2010
06.07.2010
07.07.2010
08.07.2010
09.07.2010
10.07.2010
11.07.2010
Week3.Days:
12.07.2010
13.07.2010
14.07.2010
15.07.2010
16.07.2010
17.07.2010
18.07.2010
Week4.Days:
19.07.2010
20.07.2010
21.07.2010
22.07.2010

How would you do the algo?


Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
AndyAinscowFreelance programmer / Consultant

Commented:
This sounds like homework - so advice only.

You have three conditions (at most).  
  • The first week which may not be complete.  
  • The last week which may not be complete and could also be the first week.  
  • Intervening weeks, if any, which are complete (7 days).  
Note the 7 days - you don't need to perform any checks on the individual days, just increment by 7 some counter to determine the weeks (also a date object  incremented by one for printing the full date)

Author

Commented:
@Andy

homework??? This is definetaly no homework, as prove I will show you the code I have working 99%:

As I said I want another solution more generic but maybe I am ambitious...


private static List<Week> GetFullWeekList(List<DateTime> dateList)
        {
            var weekNumber = Math.Ceiling(dateList.Count / 7d); 
            var totalWeekList = new List<Week>();

            if (dateList.Count <= 7)
            {
                // Erstellte die Initale Woche Problem => Was wenn 7 tage von mittwoche bis mittwoch, dann müssen 2 weeks zurückgegeben werden!!!
                var initialWeek = GetInitialWeek(ref dateList);
                totalWeekList.Add(initialWeek);
            }
            else
            {
                // Erstellte die erste Woche
                var initialWeek = GetInitialWeek(ref dateList);

                // Erstellte die letzte Woche
                var lastWeek = GetLastWeek(ref dateList);

                totalWeekList = CreateWeekListWithDates(dateList);
                
                // Füge ein die erste Woche
                totalWeekList.Insert(0, initialWeek);

                if(lastWeek != null)
                    totalWeekList.Add(lastWeek);
            }

            return totalWeekList;
        }

        /// <summary>
        /// Überprüft die DateList ausgehend vom Startindex
        /// </summary>
        /// <param name="initialDateList"></param>
        /// <returns></returns>
        private static Week GetInitialWeek(ref List<DateTime> dateList)
        {
            var initialDateList = new List<DateTime>();
            var newweek = new Week();
            newweek.Days = new List<Day>();

         
            for (int i = 0; i < dateList.Count; i++)
            {
                if ((int)dateList[i].DayOfWeek == 1) // 1 = Montag        
                    break;
                else                  
                    initialDateList.Add(dateList[i]);                       
            }
            foreach (var date in initialDateList)
                dateList.Remove(date);

            for (int i = 0; i < initialDateList.Count; i++)
            {
                var newday = new Day();
                newday.SchooldayDate = initialDateList[i];
                newweek.Days.Add(newday);
            }
            
            return newweek;             
        }        

        private static Week GetLastWeek(ref List<DateTime> dateList)
        {
            var lastDateList = new List<DateTime>();
            for (int i = dateList.Count -1; i > 0; i--)
            {
                if (dateList[dateList.Count - 1].DayOfWeek == 0) // 0 = Sonntag              
                    break;
                else
                {
                    lastDateList.Add(dateList[dateList.Count - 1]);
                    dateList.RemoveAt(dateList.Count - 1);
                }
            }

            if (lastDateList.Count == 0)
                return null;

            // Dreht die DateTime-Werte um
            lastDateList.Reverse();

            var lastweek = new Week();           
            lastweek.Days = new List<Day>();
            for (int i = 0; i < lastDateList.Count; i++)
            {
                var newday = new Day();
                newday.SchooldayDate = lastDateList[i];
                lastweek.Days.Add(newday);
            }
            return lastweek;
        }

        /// <summary>
        /// Erstellt anhand der Anzahl der Wochen eine List mit Wochenobjekten und deren Listen mit je 7 Tagesobjekten
        /// </summary>
        /// <param name="weekNumber">Anzahl der Wochen für den Unterrichtsplaner die zu unterrichten sind</param>
        /// <returns>Gibt die allgemeine Liste mit Wochenobjekte zurück</returns>
        private static List<Week> CreateWeekListWithDates(List<DateTime> dateList)
        {
            var weekList = new List<Week>();

            int weekNumber = dateList.Count / 7;

            int counter = 0;
            for (int i = 0; i < weekNumber ; i++)
            {
                var week = new Week();
                var dayList = new List<Day>();               
                for (int j = 0; j < 7; j++)
                {
                    var day = new Day();
                    day.SchooldayDate = dateList[counter];
                    dayList.Add(day);                    
                    counter++; 
                }
                week.Days = dayList;
                weekList.Add(week);                
            }
            return weekList;
        }

Open in new window

Shahan AyyubSenior Software Engineer

Commented:
This is my solution which can help you:
http://www.experts-exchange.com/Microsoft/Development/.NET/.NET_Framework_3.x/Q_26274135.html

You need to execute in a separate console application and see the stepwise output,then I hope so you will be able to do this.


-Shahan

Author

Commented:
@Shahan

I got blind... you showed my VB code :P

I use c# only! Anyway I did some further tests and corrections to my existing code and even for crazy startdate to enddate timespans I get no exceptons but expected results. I just hoped there could be a very clever algorythm which prevents me using a GetInitWeek() and GetlastWeek() method but it seems not.
For those interested I post the working code, maybe you find something I CAN still IMPROVE ?


private static List<Week> GetFullWeekList(List<DateTime> dateList)
        {
            var totalWeekList = new List<Week>();
            
            // Erstellte die erste Woche
            var initialWeek = GetInitialWeek(ref dateList);

            // Erstellte die letzte Woche
            var lastWeek = GetLastWeek(ref dateList);

            // Erstelle allen Wochen dazwischen die immer 7 Tage haben
            totalWeekList = CreateWeekListWithDates(dateList);              
                
            // Füge ein die erste Woche
            totalWeekList.Insert(0, initialWeek);

            if(lastWeek != null)
                totalWeekList.Add(lastWeek);           

            return totalWeekList;
        }

   
private static Week GetInitialWeek(ref List<DateTime> dateList)
        {
            var initialDateList = new List<DateTime>();
            var newweek = new Week();
            newweek.Days = new List<Day>();
         
            for (int i = 0; i < dateList.Count; i++)
            {
                if ((int)dateList[i].DayOfWeek == 1) // 1 = Montag                       
                    break;               
                else               
                    initialDateList.Add(dateList[i]);                                          
            }
            foreach (var date in initialDateList)
                dateList.Remove(date);

            for (int i = 0; i < initialDateList.Count; i++)
            {
                var newday = new Day();
                newday.SchooldayDate = initialDateList[i];
                newweek.Days.Add(newday);
            }
            
            return newweek;             
        }        

        private static Week GetLastWeek(ref List<DateTime> dateList)
        {
            if (dateList.Count == 0)
                return null;

            var lastDateList = new List<DateTime>();
            for (int i = dateList.Count -1; i >= 0; i--)
            {
                if (dateList[dateList.Count - 1].DayOfWeek == 0) // 0 = Sonntag              
                    break;
                else
                {
                    lastDateList.Add(dateList[dateList.Count - 1]);
                    dateList.RemoveAt(dateList.Count - 1);
                }
            }            

            // Dreht die DateTime-Werte um
            lastDateList.Reverse();

            var lastweek = new Week();           
            lastweek.Days = new List<Day>();
            for (int i = 0; i < lastDateList.Count; i++)
            {
                var newday = new Day();
                newday.SchooldayDate = lastDateList[i];
                lastweek.Days.Add(newday);
            }
            return lastweek;
        }

 
private static List<Week> CreateWeekListWithDates(List<DateTime> dateList)
        {
            var weekList = new List<Week>();

            int weekNumber = dateList.Count / 7;

            int counter = 0;
            for (int i = 0; i < weekNumber ; i++)
            {
                var week = new Week();
                var dayList = new List<Day>();               
                for (int j = 0; j < 7; j++)
                {
                    var day = new Day();
                    day.SchooldayDate = dateList[counter];
                    dayList.Add(day);                    
                    counter++; 
                }
                week.Days = dayList;
                weekList.Add(week);                
            }
            return weekList;
        }

Open in new window

Shahan AyyubSenior Software Engineer

Commented:
I 'll be back soon here is a problem of power failure for one hour :(
Shahan AyyubSenior Software Engineer

Commented:
You area of concern is Button code:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace DateApplicationSEA
{
    public partial class Form1 : Form
    {
        List<DateTime> days = new List<DateTime>();
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            //mm-dd-yyyy
            DateTime dt = dateTimePicker1.Value;
            days.Add(dateTimePicker1.Value);
            int WeekNumber = 1;
            System.Diagnostics.Debug.WriteLine("Week" + WeekNumber + "." + "Days");
            for (int i = 0; i <= (dateTimePicker2.Value.Day - dateTimePicker1.Value.Day); i++)
            {
                if (dt.DayOfWeek != DayOfWeek.Monday)
                {
                    System.Diagnostics.Debug.WriteLine(dt.ToString().Split(' ')[0].ToString());
                    dt = dt.AddDays(1);
                    days.Add(dt);
 
                }
                else
                {
                    WeekNumber++;
                    System.Diagnostics.Debug.WriteLine("Week" + WeekNumber + "." + "Days");
                    System.Diagnostics.Debug.WriteLine(dt.ToString());
                    dt = dt.AddDays(1);
                    days.Add(dt); 
                }
            }
            System.Diagnostics.Debug.WriteLine("********************Printing*************************");
            foreach (DateTime element in days)
            {
                System.Diagnostics.Debug.WriteLine(element.ToString()); 
            }
        }
    }
}

Open in new window

Shahan AyyubSenior Software Engineer

Commented:
Output will be seen in 'Output Window'.

View-> Output
Shahan AyyubSenior Software Engineer

Commented:
Correct line 40:

40: System.Diagnostics.Debug.WriteLine(dt.ToString().Split(' ')[0].ToString());

Author

Commented:
My area of concern? Do you mean you have found a logical error in my code?

I run your code and your logic is totally wrong.

this will never work: for (int i = 0; i <= (dateTimePicker2.Value.Day - dateTimePicker1.Value.Day); i++)

startdate: 03.07.2010 enddate: 02.09.2010

what i get in your for-condition is  i <= (3 - 2) does not make sense eh? ;-)
Shahan AyyubSenior Software Engineer

Commented:
No, just execute this code: you will get the output you have defined in question.

        List<DateTime> days = new List<DateTime>();

        private void button1_Click(object sender, EventArgs e)
        {
            //mm-dd-yyyy
            DateTime dt = dateTimePicker1.Value;
            days.Add(dateTimePicker1.Value);
            int WeekNumber = 1;
            System.Diagnostics.Debug.WriteLine("Week" + WeekNumber + "." + "Days");
            for (int i = 0; i <= (dateTimePicker2.Value.Day - dateTimePicker1.Value.Day); i++)
            {
                if (dt.DayOfWeek != DayOfWeek.Monday)
                {
                    System.Diagnostics.Debug.WriteLine(dt.ToString().Split(' ')[0].ToString());
                    dt = dt.AddDays(1);
                    days.Add(dt);
 
                }
                else
                {
                    WeekNumber++;
                    System.Diagnostics.Debug.WriteLine("Week" + WeekNumber + "." + "Days");
                    System.Diagnostics.Debug.WriteLine(dt.ToString());
                    dt = dt.AddDays(1);
                    days.Add(dt);
                }
            }
            System.Diagnostics.Debug.WriteLine("********************Printing*************************");            foreach (DateTime element in days)            {                System.Diagnostics.Debug.WriteLine(element.ToString());            }        }
    }

You can remove the Italic portion from the code which was used for printing.
Shahan AyyubSenior Software Engineer

Commented:
Sorry I didn't check your above post. I am checking it again.



Shahan AyyubSenior Software Engineer

Commented:
Okay I got it why you had been given a chance for such kind of comments:what i get in your >>> for-condition is  i <= (3 - 2) does not make sense  eh? ;-)

Actually the link I posted you was belongs to the calculation within a month so  used the same methodology and do calculation for within a month.

So, try like as mention in below code: i.e., use this line as condition:
i <= Math.Ceiling(dateTimePicker2.Value.Subtract(dateTimePicker1.Value).TotalDays)

The code is showing the result upto 10th week within the timespan you had given above i.e., startdate: 03.07.2010 enddate: 02.09.2010

So ,if you want to reset the WeekNumber after 4 or 5, you can.

List<DateTime> days = new List<DateTime>();
        private void button1_Click(object sender, EventArgs e)
        {
            DateTime dt = dateTimePicker1.Value;
            days.Add(dateTimePicker1.Value);
            int WeekNumber = 1;
            System.Diagnostics.Debug.WriteLine("Week" + WeekNumber + "." + "Days");
            for (int i = 0; i <= Math.Ceiling(dateTimePicker2.Value.Subtract(dateTimePicker1.Value).TotalDays ); i++)
            {
                if (dt.DayOfWeek != DayOfWeek.Monday)
                {
                    System.Diagnostics.Debug.WriteLine(dt.ToString().Split(' ')[0].ToString());
                    dt = dt.AddDays(1);
                    days.Add(dt);
                }
                else
                {
                    WeekNumber++;
                    System.Diagnostics.Debug.WriteLine("Week" + WeekNumber + "." + "Days");
                    System.Diagnostics.Debug.WriteLine(dt.ToString().Split(' ')[0].ToString());
                    dt = dt.AddDays(1);
                    days.Add(dt); 
                }
            }
            ShowRes();
        }

        public void ShowRes()
        {
            System.Diagnostics.Debug.WriteLine("********************Printing*************************");
            foreach (DateTime element in days)
            {
                System.Diagnostics.Debug.WriteLine(element.ToString().Split(' ')[0].ToString());
            }
        }

Open in new window

anarki_jimbelSenior Developer

Commented:
Try the following code - should be quite transparent to understand :)
        private void button2_Click(object sender, EventArgs e)
        {
            List<DateTime> dates = new List<DateTime>();
            for (int i = 1; i <= 22; i++)
            {
                DateTime dt = new DateTime(2010, 07, i);
                dates.Add(dt);
            }

            List<List<DateTime>> weeks = new List<List<DateTime>>();// list that contains "buckets" of days

            List<DateTime> currentWeek = new List<DateTime>();// current bucket
            foreach (DateTime dt in dates)
            {

                if (dt.DayOfWeek != DayOfWeek.Monday)
                {
                    currentWeek.Add(dt);
                }
                else
                {
                    if (currentWeek.Count>0)
                        weeks.Add(currentWeek);

                    currentWeek = new List<DateTime>();
                    currentWeek.Add(dt);
                }
            }
            if (currentWeek.Count > 0)// add last week to the list of weeks
                weeks.Add(currentWeek);

            // print output
            for(int i = 0; i< weeks.Count; i++)
            {
                System.Diagnostics.Debug.WriteLine("Weeks" + (i+1) + ".Days");
                List<DateTime> week = weeks[i];
                foreach (DateTime dt in week)
                {
                    System.Diagnostics.Debug.WriteLine(dt.ToShortDateString());
                }
            }

        }

Open in new window

Senior Developer
Commented:
Just looking again at my post. May be it lacks comments.

The first loop is just to prepare list of dates - I didn't want to complicate everything with datetimepickers.
The real code (logic) that's doing a job:
            List<List<DateTime>> weeks = new List<List<DateTime>>();// list that contains "buckets" of days

            List<DateTime> currentWeek = new List<DateTime>();// current bucket
            foreach (DateTime dt in dates)
            {

                if (dt.DayOfWeek != DayOfWeek.Monday)
                {
                    currentWeek.Add(dt);
                }
                else
                {
                    if (currentWeek.Count>0)
                        weeks.Add(currentWeek);

                    currentWeek = new List<DateTime>();
                    currentWeek.Add(dt);
                }
            }
            if (currentWeek.Count > 0)// add last week to the list of weeks
                weeks.Add(currentWeek);

What's good about it - we have all our dates sorted into "week" buckets. First and last buckets may contain less than, e.g., 7 days. Now as we put these dates into buckets, we may do any processing to these buckets, not just simple printing, but, e.g., calculate how many hours we have for a week (bucket), how many "full" backets (containing 7 days) etc. Kind of OOP approach :)
AndyAinscowFreelance programmer / Consultant
Commented:
OK, so it isn't homework.
If I understand you correctly the week you talk about doesn't necessarily start on a sunday, it could be wednesday - no problems, a full week still has 7 days.  The logic I said initially still stands.
  • The first week which may not be complete.  
  • The last  week which may not be complete and could also be the first week.  
  • Intervening  weeks, if any, which are complete (7 days).  
So - you can't simplify it beyond those.

Data storage - either a list of weeks, each week containing a list of days OR a list of another object that has the date and the week number.  (It depends on what you want to do).  <If all you require is a print out then you don't even need any data storage>

The first week.  Check the start day and compare it to the day the week starts on - so you now know how many days can be in that week and add those days into the week.  Don't forget to check the end date just in case that is before the end of the week.
Now just add weeks in a simple loop of 7 individual days (again check for the end date being before the end of the week)

If you look at the logic of your solution I think it is a little too complex - you shouldn't require a function for the last week generation

Author

Commented:
@anarki_jimbel:

Your code was fine for doing what YOU wanted. But when I look and test your code well and try to integrate my requirements into your algo I fail :/

Look again please at my classes. I am using List and a Week has many  Days aka List with properties...

@Andy

I have reduced the size of my GetLastWeek method by 50 percent and have built it into the CreateWeekListWithDates method and changed it too:


private static List<Week> CreateWeekListWithDates(List<DateTime> dateList)
        {
            var weekList = new List<Week>();
            int weekNumber = dateList.Count / 7;

            int counter = 0;
            for (int i = 0; i < weekNumber ; i++)
            {
                var week = new Week();
                var dayList = new List<Day>();               
                for (int j = 0; j < 7; j++)
                {
                    var day = new Day();
                    day.SchooldayDate = dateList[counter];
                    dayList.Add(day);                   
                    counter++; 
                }
                week.Days = dayList;
                weekList.Add(week);                
            }
            
            // Last Week
            var lastWeek = new Week();
            var dayListLastWeek = new List<Day>();  
            for (int i = 0; i < dateList.Count % 7; i++)
            {
                    var day = new Day();
                    day.SchooldayDate = dateList[i];
                    dayListLastWeek.Add(day);            
                    
            }
            lastWeek.Days = dayListLastWeek;
            weekList.Add(lastWeek);
            
            return weekList;
        }

Open in new window

Author

Commented:
@Andy

I am sorry I was too fast giving the points, actually you deserve points too, where I am not 100% satisfied with the other solution, well... that one moment all looks fine until I saw its a List with List and not List what I would need... and implementing that I get nearly the same code I have now...
Shahan AyyubSenior Software Engineer

Commented:
did you test my code ?

Author

Commented:
ups did an error in my last posted code... forget about the modulo operator :P

@Shahan

jesus too many Masters here I can not differentiate... I will test your code hopefully tomorrow now I am tired... and I will come back here!

Author

Commented:
@Shahan

Just reRead what you wrote:

"No, just execute this code: you will get the output you have defined in question.

       List days = new List();"

Thats not right I never asked for a List of type Datetime. Look what my inital question is =>

"Basing on my above dateList I should get this  List of Weeks as result:"

:)
anarki_jimbelSenior Developer

Commented:
MSFanboy, you can reassign point - not a problem. Not exactly sure how to but sk an admin.

Second, I didn't understand what the problem is? Can you be more specific - what's not working?
anarki_jimbelSenior Developer

Commented:
OK, have a look at the version with your classes. Honestly, I don't quite understand the Day class but anyway - this should be enough for you to incorporate the solution into your code:
        private void button2_Click(object sender, EventArgs e)
        {
            List<DateTime> dates = new List<DateTime>();
            for (int i = 1; i <= 22; i++)
            {
                DateTime dt = new DateTime(2010, 07, i);
                dates.Add(dt);
            }

            List<Week> weeks = new List<Week>();// list that contains "buckets" of days

            Week currentWeek = new Week();// current bucket
            int idCounter = 1;
            foreach (DateTime dt in dates)
            {

                if (dt.DayOfWeek != DayOfWeek.Monday)
                {
                    Day d = new Day();
                    d.MeetingDate = dt;
                    currentWeek.Days.Add(d);
                }
                else
                {
                    if (currentWeek.Days.Count>0){
                        currentWeek.WeekID = idCounter++;
                        weeks.Add(currentWeek);
                    }

                    currentWeek = new Week();
                    Day d = new Day();
                    d.MeetingDate = dt;
                    currentWeek.Days.Add(d);
                }
            }
            if (currentWeek.Days.Count > 0){// add last week to the list of weeks
                currentWeek.WeekID = idCounter;// this is last week - no more point to increase counter :)
                weeks.Add(currentWeek);
            }
            // print output
            for(int i = 0; i< weeks.Count; i++)
            {
                Week theweek = weeks[i];
                System.Diagnostics.Debug.WriteLine("Weeks" + theweek.WeekID + ".Days");

                foreach (Day d in theweek.Days)
                {
                    System.Diagnostics.Debug.WriteLine(d.MeetingDate.ToShortDateString());
                }
            }

        }

 

    }

    public class Week
    {
        private int _id;
        public int WeekID {
            get
            {
                return _id;
            }
            set{
                _id = value;
            }
        }
        private List<Day> _days = new List<Day>();
        public List<Day> Days { 
            get{
                return _days;
            }
        }
    }

    public class Day
    {
        private DateTime _day;
        public DateTime MeetingDate {
            get{
                return _day;
            }
            set{
                _day = value;
            }
        }
    }

Open in new window

AndyAinscowFreelance programmer / Consultant

Commented:
I've requested a moderator reopens the question.  I'll have a look later this morning at the latest posts in detail and see if I can suggest anything.
anarki_jimbelSenior Developer

Commented:
Suggest what?!  How to divide my points? :)

I'd like to hear from the author of the post - what she thinks about my latest code. Having Week and Day classes suite very well to my approach.
AndyAinscowFreelance programmer / Consultant

Commented:
From a previous comment by the author:

@Andy

I am sorry I was too fast giving the points, actually you  deserve points too, where I am not 100% satisfied with the other  solution

AndyAinscowFreelance programmer / Consultant

Commented:
An alternative without assigning days into weeks    

public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            DateTime dteStart = this.dateTimePicker1.Value;
            DateTime dteEnd = this.dateTimePicker2.Value;

            List<CDay> lstDays = new List<CDay>();
            DateTime dteCurrent = dteStart;
            int iWeek = 1;
            int iDayInWeek = 1;    //set to another value if the start day is NOT the first day of the week

            bool bContinue = true;
            while (bContinue)
            {
                CDay day = new CDay();
                day.m_iWeek = iWeek;
                day.m_dte = dteCurrent;
                lstDays.Add(day);
                dteCurrent = dteCurrent.AddDays(1);

                iDayInWeek++;

                if (dteCurrent.Date <= dteEnd.Date)
                {
                    if (iDayInWeek > 7)
                    {
                        iDayInWeek = 1;
                        iWeek++;
                    }
                }
                else
                    bContinue = false;
            }


            this.listBox1.Items.Clear();
            iWeek = 0;
            foreach (CDay dy in lstDays)
            {
                if (dy.m_iWeek != iWeek)
                {
                    iWeek = dy.m_iWeek;
                    this.listBox1.Items.Add(string.Format("Week {0}", iWeek));
                }
                this.listBox1.Items.Add(dy.m_dte.ToShortDateString());
            }
        }
    }


    public class CDay
    {
        public CDay() { m_iWeek = 0; }
        ~CDay() { }

        public DateTime m_dte;
        public int m_iWeek;
    }
   

0012.jpg
AndyAinscowFreelance programmer / Consultant

Commented:
Changing the initial day of the week to 3 for example results in


0013.jpg

Author

Commented:
back guys :)

@Anarki

"I'd like to hear from the author of the post - what she thinks about my latest code. Having Week and Day classes suite very well to my approach"

- Check your if/else clause both declare a "d" variable, that is not compiling... (do you type c# in notepad?) ;P
- You have no  var days = new List collection so you will get a NULLRefException

someone knows how I can pm a admin to ReOpen that thread?
AndyAinscowFreelance programmer / Consultant

Commented:
You click the 'request attention' link on the first comment - your question.

ps. I've done so already - see
http://www.experts-exchange.com/Community_Support/General/Q_26308605.html

Author

Commented:
@Anarki

damn first comment was my fault I had this at top of the code: DateTime d = DateTime.Now;

so its triple "d" sorry...

Author

Commented:
@Anarki

see your code that I have changed with the List days

the problem with that code is that I can not create a days list when the current day is != Monday because if its a saturday a days list is created, next day its a sunday again a days list is created.

How would you solve that dilemma in your Code?

@Andy

thx seems we posted the same time.
var weeks = new List<Week>();
            List<Day> days;
            Week currentWeek = new Week();// current bucket           
            
            foreach (DateTime dt in dates)
            {
                if (dt.DayOfWeek != DayOfWeek.Monday)
                {
                    Day d = new Day();
                    days = new List<Day>();
                    d.SchooldayDate = dt;
                    currentWeek.Days = days;
                    currentWeek.Days.Add(d);
                }
                else
                {
                    if (currentWeek.Days.Count>0)                  
                        weeks.Add(currentWeek);
                   
                    currentWeek = new Week();
                    Day d = new Day();
                    days = new List<Day>();
                    d.SchooldayDate = dt;
                    currentWeek.Days.Add(d);
                }
            }
            if (currentWeek.Days.Count > 0)               
                weeks.Add(currentWeek);

Open in new window

anarki_jimbelSenior Developer

Commented:
MSFanboy, you won't believe but I ALWAYS run my code before posting here. If not - I tell it's not tested :)

I checked - my code is running. Not sure why it was not compiling on your computer... Probably, you had a variable with the same name elsewhere. I haven't "var days = new List<Day>" - I was not using it anywhere. So - I had no any null exceptions :)
Wow! I've got! You didn't see my Week class - so don't blame me! :) . It defines :

private List<Day> _days = new List<Day>();

Really, what you do, I mean creatin Days and assigning to a current week  - is a bad practice. Week's Days collection should be read only. Common practice - one cannot reassign entire collection from outside. That's why I create it in the Week class (really, it should be in a constructor - but I was lazy to write a constructor :))

OK, I fixed your problem - see the snippet (look also at my new class definitions). But I'd recommend to use my previous version of Week and main code...

As a matter of fact - I hate "var". This is MS step into past, into time of Visual Basic 5 etc. :)
        private void button2_Click(object sender, EventArgs e)
        {
            List<DateTime> dates = new List<DateTime>();
            for (int i = 1; i <= 22; i++)
            {
                DateTime dt = new DateTime(2010, 07, i);
                dates.Add(dt);
            }

            List<Week> weeks = new List<Week>();// list that contains "buckets" of days
            List<Day> days = new List<Day>();
            Week currentWeek = new Week();// current bucket
            currentWeek.Days = days;
            int idCounter = 1;
            foreach (DateTime dt in dates)
            {

                if (dt.DayOfWeek != DayOfWeek.Monday)
                {
                    Day d = new Day();
                    d.SchooldayDate = dt;
                    currentWeek.Days.Add(d);
                }
                else
                {
                    if (currentWeek.Days.Count>0){
                        currentWeek.WeekID = idCounter++;
                        weeks.Add(currentWeek);
                    }

                    currentWeek = new Week();
                    days = new List<Day>();
                    currentWeek.Days = days;
                    Day d = new Day();
                    d.SchooldayDate = dt;
                    currentWeek.Days.Add(d);
                }
            }
            if (currentWeek.Days.Count > 0){// add last week to the list of weeks
                currentWeek.WeekID = idCounter;// this is last week - no more point to increase counter :)
                weeks.Add(currentWeek);
            }
            // print output
            for(int i = 0; i< weeks.Count; i++)
            {
                Week theweek = weeks[i];
                System.Diagnostics.Debug.WriteLine("Weeks" + theweek.WeekID + ".Days");

                foreach (Day d in theweek.Days)
                {
                    System.Diagnostics.Debug.WriteLine(d.SchooldayDate.ToShortDateString());
                }
            }

        }
=================================
    public class Week
    {
        private int _id;
        public int WeekID {
            get
            {
                return _id;
            }
            set{
                _id = value;
            }
        }
        private List<Day> _days; // = new List<Day>();
        public List<Day> Days { 
            get{
                return _days;
            }
            set{
                _days = value;
            }
        }
    }

    public class Day
    {
        private DateTime _day;
        public DateTime SchooldayDate {
            get{
                return _day;
            }
            set{
                _day = value;
            }
        }
    }

Open in new window

anarki_jimbelSenior Developer

Commented:
Ha, I believe I sleep when you all awake :) And vice versa. Bit hard to communicate.
I have to watch FIFA World Cup e.g., at 2 A.m.! - in a long winter night :)

Author

Commented:
@Anarki

yo yo bro still 17 minutes time to watch wm soccer :P

About "var" your totally right just trying to get rid of it. Got used to it last month but do not like it anymore.

About readonly collection days your also totally right and I totally forgot what I learnt former times...

Of course List should/could be created in the Week`s constructor.

I attached the working code.

@Andy

You also put up some code but I really like Anarki`s solution. But you gave good advise so you get 100 points :P

Thank you both especially Anarki!
List<Week> weeks = new List<Week>();
            Week currentWeek = new Week();         
            foreach (DateTime dt in dates)
            {
                if (dt.DayOfWeek != DayOfWeek.Monday)                
                    currentWeek.Days.Add(new Day() {  SchooldayDate = dt });               
                else
                {
                    if (currentWeek.Days.Count > 0)                  
                        weeks.Add(currentWeek);                    

                    currentWeek = new Week();                    
                    currentWeek.Days.Add(new Day() { SchooldayDate = dt });
                }
            }
            if (currentWeek.Days.Count > 0) // last week
                weeks.Add(currentWeek);

 public class Week
    {
        private List<Day> _days;

        public Week()
        {
            _days = new List<Day>();
        }

        public List<Day> Days
        {
            get { return _days; }            
        }

Open in new window

Author

Commented:
:)
AndyAinscowFreelance programmer / Consultant

Commented:
Thanks - there are pluses and minuses to both techniques.  It really depends on what you need to use the collection for in the end.
anarki_jimbelSenior Developer

Commented:
Germany lost... I waked up at 6 in the morning to support them... Spain was good, really good...

Anyway, thanks everyone here - I enjoyed the discussion :)

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial