Việt
Việt

Reputation: 13

Count occurrence for each day of the week between two dates

I want to count occurrences, for each day of the week, between two given dates.

For example:

Between 20/07/2014 to 27/7/2014, an 8 day span, there were:

Sunday=2, monday=1, tuesday=1,...

Upvotes: 1

Views: 2349

Answers (6)

Ehsan Sajjad
Ehsan Sajjad

Reputation: 62488

you can achieve it using Linq:

DateTime StartDate = DateTime.Now.AddDays(-14);
DateTime EndDate = DateTime.Now;
DayOfWeek day = DayOfWeek.Monday;

First get the all days between two dates:

List<DateTime> dates = Enumerable.Range(0, (int)((EndDate - StartDate).TotalDays) + 1)
                      .Select(n => StartDate.AddDays(n))
                      .ToList();

Now get Count on the base of day, currently it will get Count of Monday:

var MondayCount = dates.Count(x => x.DayOfWeek == day);

FIDDLE:

https://dotnetfiddle.net/ZopkFY

Upvotes: 0

Peter Kiss
Peter Kiss

Reputation: 9319

    public static Dictionary<DayOfWeek, int> CountDayOfWeeks(DateTime @from, DateTime to)
    {
        var start = @from.Date;

        var ret = Enum.GetValues(typeof(DayOfWeek)).Cast<DayOfWeek>().ToDictionary(x => x, x => 0);

        while (start <= to)
        {
            ret[start.DayOfWeek]++;
            start = start.AddDays(1);
        }

        return ret;
    }

Upvotes: 0

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 476557

You better convert the days first to DateTime instances:

DateTime d1 = new DateTime(2014,07,20);
DateTime d2 = new DateTime(2014,07,27);

Next you calculate the total days between the two dates:

int days = (int) Math.Floor((d2-d1).TotalDays)+1;

As well as the day of the week of the first date:

int dow = (int) d1.DayOfWeek;

Now we devide the number of days by seven and assign that number to all days: since this is the minimum occurences for each day:

int d7 = days/7;
int[] counts = new int[7];
for(int i = 0; i < 7; i++) {
    counts[i] = d7;
}

The remainder of the days are distributed with the day of the week of d1 first:

int remainder = days-7*d7;
int dowi = dow;
while(remainder > 0) {
    counts[dowi]++;
    dowi = (dowi+1)%7;//next day of the week
    remainder--;
}

Then we can return the arrray:

return counts;

Full method:

public static int[] countDelta (DateTime d1, DateTime d2) {
    int days = (int) Math.Floor((d2-d1).TotalDays)+1;
    int dow = (int) d1.DayOfWeek;
    int d7 = days/7;
    int[] counts = new int[7];
    for(int i = 0; i < 7; i++) {
        counts[i] = d7;
    }
    int remainder = days-7*d7;
    int dowi = dow;
    while(remainder > 0) {
        counts[dowi]++;
        dowi = (dowi+1)%7;//next day of the week
        remainder--;
    }
    return counts;
}

The result of a csharp interactive session:

csharp> Foo.countDelta(new DateTime(2014,07,20),new DateTime(2014,07,27));
{ 2, 1, 1, 1, 1, 1, 1 }

The method runs in constant time (if the dates differ much, this will not have an impact on performance). The only constraint is that calendar must be modern: if somewhere in history, people skipped a few "days of the week", this could result in some problems.

Upvotes: 1

shree.pat18
shree.pat18

Reputation: 21757

Try this:

DateTime start = new DateTime(2014,07,20);
DateTime end = new DateTime(2014,07,27);
TimeSpan ts = end - start;
int limit = ts.Days;
var result = Enumerable.Range(0,limit+1)
            .Select(x => start.AddDays(x))
            .GroupBy(x => x.DayOfWeek)
            .Select(x => new {day = x.Key, count = x.Count()});

We create a range of dates from start to end, inclusive of both dates, and then group by the day of week to get the days and corresponding counts.

Demo

Upvotes: 3

Winson
Winson

Reputation: 787

the simple way is for loop each day in the period, and use switch case or if else to check the current date.DayOfWeek to count and save the week number, something like the following:

int mondays = 0;
switch(current.DayOfWeek){
    case DayOfWeek.Monday:
         mondays++;
    break;
    ...
}

Upvotes: 0

Ivan Zub
Ivan Zub

Reputation: 805

You can try something like this. It may be not the best solution, but it's the first that came in mind:

        var startDate = DateTime.Now;
        var endDate = startDate.AddDays(15);

        var rusultDictionary = new Dictionary<DayOfWeek, int>();

        while (!startDate.Date.Equals(endDate.Date))
        {
            rusultDictionary[startDate.DayOfWeek] = rusultDictionary.ContainsKey(startDate.DayOfWeek) ? rusultDictionary[startDate.DayOfWeek] + 1 : 1;
            startDate = startDate.AddDays(1);
        }

Upvotes: 0

Related Questions