GuidoG
GuidoG

Reputation: 12014

Count number of including weeks between 2 dates

I need to get the number of weeks between 2 dates.
A week for me is monday to sunday.
So if the first date is on a saturday than this week should be included.
if the second date is on a monday than this week should be included.

What is the most efficient way to do this ?

example :

startdate   enddate      nbr of weeks
17/09/2016  26/09/2016   3 weeks
17/09/2016  25/09/2016   2 weeks
19/09/2016  26/09/2016   2 weeks
12/09/2016  25/09/2016   2 weeks

I found much answers for this, like this one for example how to calculate number of weeks given 2 dates? but they all end up with dividing the days with 7 and that does not gives the result I need.

Upvotes: 2

Views: 6227

Answers (3)

Slai
Slai

Reputation: 22866

A bit "simplified", because the Monday is needed just for the start date:

static int weeks(DateTime d1, DateTime d2) { 
    var daysSinceMonday = ((int)d1.DayOfWeek + 6) % 7;
    return ((d2 - d1).Days + daysSinceMonday) / 7 + 1; 
}

Upvotes: 5

matthijsb
matthijsb

Reputation: 909

See my method below, I "strechted" the weeks to monday untill sunday, and then calculated the total days / 7

    public static void Main(string[] args)
    {
        Console.WriteLine(CalculateWeeks(new DateTime(2016, 9, 17), new DateTime(2016, 9, 26)));
        Console.WriteLine(CalculateWeeks(new DateTime(2016, 9, 17), new DateTime(2016, 9, 25)));
        Console.WriteLine(CalculateWeeks(new DateTime(2016, 9, 19), new DateTime(2016, 9, 26)));
        Console.WriteLine(CalculateWeeks(new DateTime(2016, 9, 12), new DateTime(2016, 9, 25)));

    }

    public static double CalculateWeeks(DateTime from, DateTime to)
    {
        if (to.DayOfWeek != DayOfWeek.Sunday)
            to = to.Add(new TimeSpan(7- (int) to.DayOfWeek, 0, 0, 0)).Date;
        return Math.Ceiling((to - from.Subtract(new TimeSpan((int)from.DayOfWeek - 1, 0, 0, 0)).Date).TotalDays / 7);
    }

Upvotes: 3

Jon Skeet
Jon Skeet

Reputation: 1499860

The simplest way is probably to write a method to get the start of a week. Then you can subtract one date from another, divide the number of days by 7 and add 1 (to make it inclusive).

Personally I'd use Noda Time for all of this, but using DateTime:

// Always uses Monday-to-Sunday weeks
public static DateTime GetStartOfWeek(DateTime input)
{
    // Using +6 here leaves Monday as 0, Tuesday as 1 etc.
    int dayOfWeek = (((int) input.DayOfWeek) + 6) % 7;
    return input.Date.AddDays(-dayOfWeek);
}

public static int GetWeeks(DateTime start, DateTime end)
{
    start = GetStartOfWeek(start);
    end = GetStartOfWeek(end);
    int days = (int) (end - start).TotalDays;
    return (days / 7) + 1; // Adding 1 to be inclusive
}

Complete example:

using System;

class Program
{
    static void Main (string[] args)
    {
        ShowWeeks(new DateTime(2016, 9, 17), new DateTime(2016, 9, 26));
        ShowWeeks(new DateTime(2016, 9, 17), new DateTime(2016, 9, 25));
        ShowWeeks(new DateTime(2016, 9, 19), new DateTime(2016, 9, 26));
        ShowWeeks(new DateTime(2016, 9, 12), new DateTime(2016, 9, 25));
    }

    static void ShowWeeks(DateTime start, DateTime end)
    {
        int weeks = GetWeeks(start, end);
        Console.WriteLine($"{start:d} {end:d} {weeks}");
    }

    // Always uses Monday-to-Sunday weeks
    public static DateTime GetStartOfWeek(DateTime input)
    {
        // Using +6 here leaves Monday as 0, Tuesday as 1 etc.
        int dayOfWeek = (((int) input.DayOfWeek) + 6) % 7;
        return input.Date.AddDays(-dayOfWeek);
    }

    public static int GetWeeks(DateTime start, DateTime end)
    {
        start = GetStartOfWeek(start);
        end = GetStartOfWeek(end);
        int days = (int) (end - start).TotalDays;
        return (days / 7) + 1; // Adding 1 to be inclusive
    }
}

Output (in my UK locale):

17/09/2016 26/09/2016 3
17/09/2016 25/09/2016 2
19/09/2016 26/09/2016 2
12/09/2016 25/09/2016 2

Upvotes: 7

Related Questions