578

How do I find the start of the week (both Sunday and Monday) knowing just the current time in C#?

Something like:

DateTime.Now.StartWeek(Monday);
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
GateKiller
  • 74,180
  • 73
  • 171
  • 204

34 Answers34

922

Use an extension method:

public static class DateTimeExtensions
{
    public static DateTime StartOfWeek(this DateTime dt, DayOfWeek startOfWeek)
    {
        int diff = (7 + (dt.DayOfWeek - startOfWeek)) % 7;
        return dt.AddDays(-1 * diff).Date;
    }
}

Which can be used as follows:

DateTime dt = DateTime.Now.StartOfWeek(DayOfWeek.Monday);
DateTime dt = DateTime.Now.StartOfWeek(DayOfWeek.Sunday);
TylerH
  • 20,799
  • 66
  • 75
  • 101
Compile This
  • 11,892
  • 2
  • 25
  • 22
  • 29
    You can simplify this as follows: `int diff = dayOfWeek - dt.DayOfWeek; return dt.AddDays(diff).Date;` – Troy Mar 28 '11 at 23:28
  • 20
    Troy, I do not believe your code works if the given date is a Sunday and your start of week is Monday. It will return (Sunday + 1) instead of (Sunday - 6) – Aaron Hoffman Apr 23 '12 at 14:55
  • 2
    This doesn't work if `dt` is UTC and is already the start of the week e.g. `2012-09-02 16:00:00Z` which is `Mon, 03 Sep 2012 00:00:00` in local time. So it needs to convert `dt` to local time or do something a bit smarter. It would also need to return the result as UTC if the input was UTC. – row1 Sep 06 '12 at 04:12
  • 1
    @row1 `DateTime.Parse("2012-09-02 16:00:00Z")` returns the local-time equivalent, and this method correctly returns the same time, as a local time. If you use `DateTime.Parse("2012-09-02 16:00:00Z").ToUniversalTime()` to explicitly pass the UTC time, this method correctly returns 6 days, 16 hours earlier, as a UTC time. It's working exactly as I'd expect. – Rawling Jan 22 '13 at 10:51
  • @Rawling the result of working with a UTC kind via .ToUniversalTime() is not expected for me--I expect it to return 2012-09-02 16:00:00Z. I also don't think using .Date on a UTC date makes sense as you could easily lose a day if you are passing in UTC dates but expecting local results...well doesn't make sense for my usage anyway. – row1 Jan 23 '13 at 00:51
  • @Troy , your code is actually pretty close to the one for **EndOfWeek** ;-). `int diff = endOfWeek - dt.DayOfWeek; return dt.AddDays(diff).Date;` – Sometowngeek Jul 21 '16 at 12:59
  • 5
    This would be off by one day for me sometimes. It worked for me once I stripped the time component from `dt`. I used `int diff = dt.Date.DayOfWeek - startOfWeek;` – Vincent Saelzler May 26 '17 at 17:43
  • Which part of the above code binds the StartOfWeel method to DateTime.Now? I thought that the "token" that follows "this" keyword is the class name but in this case its the type of the parameter. I am confused. Thanks for taking the time to answer. – NoChance Feb 23 '22 at 01:35
  • 1
    @NoChance DateTime.Now is actually a getter which creates a new DateTime. This answer is extending DateTime. This happens because the function is static and the first parameter uses 'this' ... I think there is also the need for it be in a separate static class (by convention usually uses 'Extensions' in the class name) – DAG Jan 20 '23 at 13:35
  • Thanks @DAG, never used "this" in like in here: "StartOfWeek(this DateTime...". – NoChance Jan 20 '23 at 20:25
124

The quickest way I can come up with is:

var sunday = DateTime.Today.AddDays(-(int)DateTime.Today.DayOfWeek);

If you would like any other day of the week to be your start date, all you need to do is add the DayOfWeek value to the end

var monday = DateTime.Today.AddDays(-(int)DateTime.Today.DayOfWeek + (int)DayOfWeek.Monday);

var tuesday = DateTime.Today.AddDays(-(int)DateTime.Today.DayOfWeek + (int)DayOfWeek.Tuesday);
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Eric
  • 2,207
  • 2
  • 16
  • 16
  • 3
    the simplest answers are the best, this one worked fine, but culture depended – Cerveser Oct 08 '14 at 19:06
  • 19
    In Latvia week starts at Monday.. Actually.. I always wonder how can a week start on Sunday.. seems awkward to me.. ;) – 0xDEAD BEEF Feb 01 '16 at 16:39
  • This solution is good. In addition you could Make the start of the week any day by adding the DayOfWeek you want to start on. var sunday = DateTime.Today.AddDays(-(int)DateTime.Today.DayOfWeek); var monday = DateTime.Today.AddDays(-(int)DateTime.Today.DayOfWeek + (int)DayOfWeek.Monday); – Loligans Jun 14 '16 at 15:52
  • 17
    This added code does not work for the situation described by Threezol. If you want the start of the week to be Monday, on Sunday the calculation gives you the coming Monday, not the previous. – Giovanni B Aug 14 '17 at 19:49
  • 8
    Yes.. For sunday, it gives the next Modnay.. not the previous :P – Nameless Feb 14 '18 at 06:27
  • to always get the correct monday, use `var monday = DateTime.Now.AddDays(-((int)DateTime.Now.DayOfWeek+6)%7);` – fwinterl Jul 21 '23 at 22:14
76

A little more verbose and culture-aware:

System.Globalization.CultureInfo ci = 
    System.Threading.Thread.CurrentThread.CurrentCulture;
DayOfWeek fdow = ci.DateTimeFormat.FirstDayOfWeek;
DayOfWeek today = DateTime.Now.DayOfWeek;
DateTime sow = DateTime.Now.AddDays(-(today - fdow)).Date;
mklement0
  • 382,024
  • 64
  • 607
  • 775
Jason Navarrete
  • 7,495
  • 6
  • 28
  • 22
  • 4
    got an error with this: today = SUNDAY; fdow = MONDAY; (today - fdow) == -1; DateTime.Now.AddDays(-(-1)).Date == DateTime.Now.AddDays(+1).Date; 01-02-2010 != 25-01-2010 !! – balexandre Jan 31 '10 at 22:44
  • 3
    If you try this on a Sunday, then it's basically doing AddDays(0 - 1) for en-GB. So it needs @Sarcastic's if statement – Chris S May 15 '11 at 14:30
  • 4
    You can also get the current culture using `CultureInfo.CurrentCulture` instead of pulling it off the thread like that. Seems like a weird way to access it. – Hank Dec 10 '12 at 18:09
  • 9
    Another issue: It is dangerous to call the `Now` property twice. If the current time happens to pass 24:00 (or 12:00 midnight) between the two calls, the date will have changed. – Jeppe Stig Nielsen Sep 02 '13 at 15:21
  • 1
    What this answer actually does is this: "inside the current .NET week (starting on sunday and ending on saturday, as per the numbering of the DayOfWeek enumeration), find the day of the .NET week that is the first one of the week in the current culture". This is probably not what you want. – Mathieu Renda Jul 12 '16 at 17:36
41

Ugly but it at least gives the right dates back

With start of week set by system:

    public static DateTime FirstDateInWeek(this DateTime dt)
    {
        while (dt.DayOfWeek != System.Threading.Thread.CurrentThread.CurrentCulture.DateTimeFormat.FirstDayOfWeek)
            dt = dt.AddDays(-1);
        return dt;
    }

Without:

    public static DateTime FirstDateInWeek(this DateTime dt, DayOfWeek weekStartDay)
    {
        while (dt.DayOfWeek != weekStartDay)
            dt = dt.AddDays(-1);
        return dt;
    }
Janspeed
  • 443
  • 4
  • 6
  • This resource helped, too: https://markb.uk/csharp-datetime-get-first-last-day-of-week-or-month.html (If you want to get the first/last day of a week or month). – FranzHuber23 May 06 '19 at 09:57
  • 2
    I have to agree this is the most foolproof method. Just look at all of the edge cases encountered by the other answers. I get the argument about efficiency, but the worst case scenario is that you start on the last day of the week and have to call AddDays six times to get back to the start. That's five more times than other solutions in the worst case, but those solutions also have to deal with other numeric calculations to derive the offset. The differential is probably insignificant in all but the most performance sensitive applications. – Blake Jul 23 '20 at 16:04
41

Using Fluent DateTime:

var monday = DateTime.Now.Previous(DayOfWeek.Monday);
var sunday = DateTime.Now.Previous(DayOfWeek.Sunday);
Simon
  • 33,714
  • 21
  • 133
  • 202
  • 36
    I'd hate to take on a dependency just for this. "Know your dependencies and kill them" seems to come to mind. :) – Esteban Araya May 28 '10 at 03:36
  • 9
    Did anyone notice HOW "Fluent" is working? Just take a look at the code. It's using a do...while loop. Don't want to call it names but if I decide to do it won't be pleasant. `public static DateTime Previous(this DateTime start, DayOfWeek day) { do { start = start.PreviousDay(); } while (start.DayOfWeek != day); return start; } ` – nsimeonov Apr 22 '13 at 21:10
  • 17
    @nsimeonov it is open source. please feel free to provide a better implementation rather then throwing stones. – Simon Apr 22 '13 at 22:57
  • 2
    @EstebanAraya: http://www.haneycodes.net/npm-left-pad-have-we-forgotten-how-to-program/ – Jim G. Mar 30 '16 at 17:16
  • 2
    @nsimeonov It seems there is a good reason for Fluent being coded that way. Edge cases around cultures with Monday as the FDoTW are avoided by using that method, inefficient though it may be. One issue in particular: when the current date is a Sunday, it is necessary to subtract 6 days to get to the Monday first day of the week. Many of the other solutions here end up adding one day instead. Note comments here in response to other methods that have been proposed. I agree though, it would be possible to do this a lot more efficiently. It's just not as trivial as it might seem at first glance. – Daniel Scott Feb 19 '22 at 01:35
13

Let's combine the culture-safe answer and the extension method answer:

public static class DateTimeExtensions
{
    public static DateTime StartOfWeek(this DateTime dt, DayOfWeek startOfWeek)
    {
        System.Globalization.CultureInfo ci = System.Threading.Thread.CurrentThread.CurrentCulture;
        DayOfWeek fdow = ci.DateTimeFormat.FirstDayOfWeek;
        return DateTime.Today.AddDays(-(DateTime.Today.DayOfWeek- fdow));
    }
}
Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794
  • 12
    neither dt nor startOfWeek is used within your function, I guess the first one should be used instead of DateTime.Today – hultqvist May 04 '10 at 08:17
  • 2
    The context of the question is wanting an additional property to use off of Datetime in the same manner as .Today or .Now. I agree this is awkward,but it's what was asked for. – Joel Coehoorn Sep 14 '11 at 20:47
  • 9
    I know this is an old answer, but it's wrong on so many levels; in addition to totally ignoring the method arguments, the math will cause it to pick a *future* date in many cases. This should have been written to use `dt` instead of `DateTime.Today`, to wrap the math in an `(offset + 7) % 7` to ensure a negative offset, to use a single-parameter method *overload* which passes the current culture's `FirstDayOfWeek` as the `startOfWeek` argument, and possibly (depending on the spec) to coerce a zero offset to a 7-day offset, so that "last Tuesday" doesn't return today if it's already Tuesday. – Aaronaught Jan 23 '12 at 15:34
13

For Monday

DateTime startAtMonday = DateTime.Now.AddDays(DayOfWeek.Monday - DateTime.Now.DayOfWeek);

For Sunday

DateTime startAtSunday = DateTime.Now.AddDays(DayOfWeek.Sunday- DateTime.Now.DayOfWeek);
Sanju
  • 1,478
  • 2
  • 20
  • 41
George Stavrou
  • 482
  • 5
  • 11
  • 1
    I had a different application need, however I used this to get me going. I like it because it is the simplest one, without any casting - keeping the operations in the same/appropriate types. – qxotk Jan 29 '19 at 15:04
  • 2
    This doesn't work when the day is Sunday. It gives the following Monday, not the start of the current week. – Grant J Nov 06 '19 at 13:31
  • Also did you copy the Sunday or the Monday. I have 2 answers One if you want for Monday and 2on if you want for Sunday..... I just tested it and it works fine to me. DateTime.Now.DayOfWeek; Sunday And Result DateTime.Now.AddDays(DayOfWeek.Sunday - DateTime.Now.DayOfWeek); {10/11/2019 4:14:55 μμ} Date: {10/11/2019 12:00:00 πμ} Day: 10 DayOfWeek: Sunday DayOfYear: 314 Hour: 16 Kind: Local Millisecond: 172 Minute: 14 Month: 11 Second: 55 Ticks: 637089992951723516 TimeOfDay: {16:14:55.1723516} Year: 2019 – George Stavrou Nov 06 '19 at 14:15
  • @GrantJ What line did you take??? I just tested and it works fine. – George Stavrou Nov 06 '19 at 14:21
  • I tried the first one, substituting your DateTime.Now with a DateTime representing Sunday 10th November 2019. It should give Monday 4th Nov 2019 but it gives Monday 11th November 2019. I've set up a fiddle demonstrating it here: https://dotnetfiddle.net/Jw3ZiO – Grant J Nov 07 '19 at 15:33
  • @GrantJ If you downgrade my answer you are wrong. First of all i answer the question. 2ond of all the start of the week According to Visual Studio as it is it is Sunday...... Not Monday.......So if it is 10/11/2019 (dd/MM/yyyy Sunday then the start of the week is 10/11/2019) Also if you want Monday and the day is 10/11/2019 then if the Week Starts at Sunday as mentioned bellow then if it is 10/11/2019 and you want the start of the week it will be 11/11/2019. You can check it here. https://learn.microsoft.com/en-us/dotnet/api/system.dayofweek?view=netframework-4.8 – George Stavrou Nov 07 '19 at 15:59
  • @GrantJ If you have different Culture Info then you should check the Joel Coehoorn answer. – George Stavrou Nov 07 '19 at 16:28
  • I think you've misunderstood the question. Check the results your answer gives compared to the accepted answer. Either that, or you've misworded your answer. I've demonstrated that the code you posted under the heading "For Monday" clearly gives Monday of the following week (regardless of culture, your answer is worded as though it's for people wanting to get the start of the week when the week starts on a Monday). – Grant J Nov 08 '19 at 08:38
  • 1
    I think I understand your answer now - it gives you the Monday, or Sunday, assuming you start the week on a Sunday which (will be appropriate only for certain cultures). However, the question was asking for a solution that gives you the **start** of the week, not for a solution that gives you a Monday or Sunday assuming the week starts on a Sunday. – Grant J Nov 08 '19 at 08:49
12

This would give you the preceding Sunday (I think):

DateTime t = DateTime.Now;
t -= new TimeSpan ((int) t.DayOfWeek, 0, 0, 0);
Skizz
  • 69,698
  • 10
  • 71
  • 108
11

This may be a bit of a hack, but you can cast the .DayOfWeek property to an int (it's an enum and since its not had its underlying data type changed it defaults to int) and use that to determine the previous start of the week.

It appears the week specified in the DayOfWeek enum starts on Sunday, so if we subtract 1 from this value that'll be equal to how many days the Monday is before the current date. We also need to map the Sunday (0) to equal 7 so given 1 - 7 = -6 the Sunday will map to the previous Monday:-

DateTime now = DateTime.Now;
int dayOfWeek = (int)now.DayOfWeek;
dayOfWeek = dayOfWeek == 0 ? 7 : dayOfWeek;
DateTime startOfWeek = now.AddDays(1 - (int)now.DayOfWeek);

The code for the previous Sunday is simpler as we don't have to make this adjustment:-

DateTime now = DateTime.Now;
int dayOfWeek = (int)now.DayOfWeek;
DateTime startOfWeek = now.AddDays(-(int)now.DayOfWeek);
ljs
  • 37,275
  • 36
  • 106
  • 124
6
using System;
using System.Globalization;

namespace MySpace
{
    public static class DateTimeExtention
    {
        // ToDo: Need to provide culturaly neutral versions.

        public static DateTime GetStartOfWeek(this DateTime dt)
        {
            DateTime ndt = dt.Subtract(TimeSpan.FromDays((int)dt.DayOfWeek));
            return new DateTime(ndt.Year, ndt.Month, ndt.Day, 0, 0, 0, 0);
        }

        public static DateTime GetEndOfWeek(this DateTime dt)
        {
            DateTime ndt = dt.GetStartOfWeek().AddDays(6);
            return new DateTime(ndt.Year, ndt.Month, ndt.Day, 23, 59, 59, 999);
        }

        public static DateTime GetStartOfWeek(this DateTime dt, int year, int week)
        {
            DateTime dayInWeek = new DateTime(year, 1, 1).AddDays((week - 1) * 7);
            return dayInWeek.GetStartOfWeek();
        }

        public static DateTime GetEndOfWeek(this DateTime dt, int year, int week)
        {
            DateTime dayInWeek = new DateTime(year, 1, 1).AddDays((week - 1) * 7);
            return dayInWeek.GetEndOfWeek();
        }
    }
}
MTCoster
  • 5,868
  • 3
  • 28
  • 49
Rabbex
  • 141
  • 1
  • 7
  • 4
    First off, welcome to the community :) There are already several high quality answers to this question, most of which were posted seven years ago when the question was asked. While it may be a worthwhile exercise to attempt to answer simple questions such as this one in order to further your programming abilities, posting this answer in its current state does not add anything to the question. If there is something novel about your answer, please take a couple sentences to explain how it's different and why that makes it better. – MTCoster Dec 05 '15 at 18:02
6

Step 1:

Create a static class

public static class TIMEE
{
    public static DateTime StartOfWeek(this DateTime dt, DayOfWeek startOfWeek)
    {
        int diff = (7 + (dt.DayOfWeek - startOfWeek)) % 7;
        return dt.AddDays(-1 * diff).Date;
    }

    public static DateTime EndOfWeek(this DateTime dt, DayOfWeek startOfWeek)
    {
        int diff = (7 - (dt.DayOfWeek - startOfWeek)) % 7;
        return dt.AddDays(1 * diff).Date;
    }
}

Step 2: Use this class to get both start and end day of the week

DateTime dt = TIMEE.StartOfWeek(DateTime.Now ,DayOfWeek.Monday);
DateTime dt1 = TIMEE.EndOfWeek(DateTime.Now, DayOfWeek.Sunday);
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Muhammad Abbas
  • 389
  • 6
  • 15
5

Putting it all together, with Globalization and allowing for specifying the first day of the week as part of the call we have

public static DateTime StartOfWeek ( this DateTime dt, DayOfWeek? firstDayOfWeek )
{
    DayOfWeek fdow;

    if ( firstDayOfWeek.HasValue  )
    {
        fdow = firstDayOfWeek.Value;
    }
    else
    {
        System.Globalization.CultureInfo ci = System.Threading.Thread.CurrentThread.CurrentCulture;
        fdow = ci.DateTimeFormat.FirstDayOfWeek;
    }

    int diff = dt.DayOfWeek - fdow;

    if ( diff < 0 )
    {
        diff += 7;
    }

    return dt.AddDays( -1 * diff ).Date;

}
Matthew Hintzen
  • 518
  • 1
  • 6
  • 11
4
var now = System.DateTime.Now;

var result = now.AddDays(-((now.DayOfWeek - System.Threading.Thread.CurrentThread.CurrentCulture.DateTimeFormat.FirstDayOfWeek + 7) % 7)).Date;
HelloWorld
  • 3,381
  • 5
  • 32
  • 58
3

Try with this in C#. With this code you can get both the first date and last date of a given week. Here Sunday is the first day and Saturday is the last day, but you can set both days according to your culture.

DateTime firstDate = GetFirstDateOfWeek(DateTime.Parse("05/09/2012").Date, DayOfWeek.Sunday);
DateTime lastDate = GetLastDateOfWeek(DateTime.Parse("05/09/2012").Date, DayOfWeek.Saturday);

public static DateTime GetFirstDateOfWeek(DateTime dayInWeek, DayOfWeek firstDay)
{
    DateTime firstDayInWeek = dayInWeek.Date;
    while (firstDayInWeek.DayOfWeek != firstDay)
        firstDayInWeek = firstDayInWeek.AddDays(-1);

    return firstDayInWeek;
}

public static DateTime GetLastDateOfWeek(DateTime dayInWeek, DayOfWeek firstDay)
{
    DateTime lastDayInWeek = dayInWeek.Date;
    while (lastDayInWeek.DayOfWeek != firstDay)
        lastDayInWeek = lastDayInWeek.AddDays(1);

    return lastDayInWeek;
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
yeasir007
  • 2,110
  • 2
  • 28
  • 43
3

Modulo in C# works bad for -1 mod 7 (it should be 6, but C# returns -1) so... a "one-liner" solution to this will look like this :)

private static DateTime GetFirstDayOfWeek(DateTime date)
{
    return date.AddDays(
        -(((int)date.DayOfWeek - 1) -
          (int)Math.Floor((double)((int)date.DayOfWeek - 1) / 7) * 7));
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
3

I tried several, but I did not solve the issue with a week starting on a Monday, resulting in giving me the coming Monday on a Sunday. So I modified it a bit and got it working with this code:

int delta = DayOfWeek.Monday - DateTime.Now.DayOfWeek;
DateTime monday = DateTime.Now.AddDays(delta == 1 ? -6 : delta);
return monday;
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Threezool
  • 453
  • 4
  • 11
  • It seems that the problem of the 'coming Monday' is culture dependant (see also answer from Eric and the comment from Cerveser.) However, if you don't need to take Sundays into account (as with usual business appointments) your formula can simplified: `dt.AddDays(DayOfWeek.Monday - dt.DayOfWeek);` – Damian Vogel Jul 11 '18 at 09:03
  • What did you modify? Code from a previous answer? Which answer? – Peter Mortensen Oct 27 '22 at 15:18
3

This would give you midnight on the first Sunday of the week:

DateTime t = DateTime.Now;
t -= new TimeSpan ((int) t.DayOfWeek, t.Hour, t.Minute, t.Second);

This gives you the first Monday at midnight:

DateTime t = DateTime.Now;
t -= new TimeSpan ((int) t.DayOfWeek - 1, t.Hour, t.Minute, t.Second);
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Glenn Slaven
  • 33,720
  • 26
  • 113
  • 165
3

The same for end of the week (in style of Compile This's answer):

    public static DateTime EndOfWeek(this DateTime dt)
    {
        int diff = 7 - (int)dt.DayOfWeek;

        diff = diff == 7 ? 0 : diff;

        DateTime eow = dt.AddDays(diff).Date;

        return new DateTime(eow.Year, eow.Month, eow.Day, 23, 59, 59, 999) { };
    }
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
F.H.
  • 1,456
  • 1
  • 20
  • 34
3

I did it for Monday, but with similar logic for Sunday.

public static DateTime GetStartOfWeekDate()
{
    // Get today's date
    DateTime today = DateTime.Today;
    // Get the value for today. DayOfWeek is an enum with 0 being Sunday, 1 Monday, etc
    var todayDayOfWeek = (int)today.DayOfWeek;

    var dateStartOfWeek = today;
    // If today is not Monday, then get the date for Monday
    if (todayDayOfWeek != 1)
    {
        // How many days to get back to Monday from today
        var daysToStartOfWeek = (todayDayOfWeek - 1);
        // Subtract from today's date the number of days to get to Monday
        dateStartOfWeek = today.AddDays(-daysToStartOfWeek);
    }

    return dateStartOfWeek;

}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
DReact
  • 606
  • 6
  • 7
2

Here is a correct solution. The following code works regardless if the first day of the week is a Monday or a Sunday or something else.

public static class DateTimeExtension
{
  public static DateTime GetFirstDayOfThisWeek(this DateTime d)
  {
    CultureInfo ci = System.Threading.Thread.CurrentThread.CurrentCulture;
    var first = (int)ci.DateTimeFormat.FirstDayOfWeek;
    var current = (int)d.DayOfWeek;

    var result = first <= current ?
      d.AddDays(-1 * (current - first)) :
      d.AddDays(first - current - 7);

    return result;
  }
}

class Program
{
  static void Main()
  {
    System.Threading.Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo("en-US");
    Console.WriteLine("Current culture set to en-US");
    RunTests();
    Console.WriteLine();
    System.Threading.Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo("da-DK");
    Console.WriteLine("Current culture set to da-DK");
    RunTests();
    Console.ReadLine();
  }

  static void RunTests()
  {
    Console.WriteLine("Today {1}: {0}", DateTime.Today.Date.GetFirstDayOfThisWeek(), DateTime.Today.Date.ToString("yyyy-MM-dd"));
    Console.WriteLine("Saturday 2013-03-02: {0}", new DateTime(2013, 3, 2).GetFirstDayOfThisWeek());
    Console.WriteLine("Sunday 2013-03-03: {0}", new DateTime(2013, 3, 3).GetFirstDayOfThisWeek());
    Console.WriteLine("Monday 2013-03-04: {0}", new DateTime(2013, 3, 4).GetFirstDayOfThisWeek());
  }
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
2

Thanks for the examples. I needed to always use the "CurrentCulture" first day of the week and for an array I needed to know the exact Daynumber.. so here are my first extensions:

public static class DateTimeExtensions
{
    //http://stackoverflow.com/questions/38039/how-can-i-get-the-datetime-for-the-start-of-the-week
    //http://stackoverflow.com/questions/1788508/calculate-date-with-monday-as-dayofweek1
    public static DateTime StartOfWeek(this DateTime dt)
    {
        //difference in days
        int diff = (int)dt.DayOfWeek - (int)CultureInfo.CurrentCulture.DateTimeFormat.FirstDayOfWeek; //sunday=always0, monday=always1, etc.

        //As a result we need to have day 0,1,2,3,4,5,6 
        if (diff < 0)
        {
            diff += 7;
        }
        return dt.AddDays(-1 * diff).Date;
    }

    public static int DayNoOfWeek(this DateTime dt)
    {
        //difference in days
        int diff = (int)dt.DayOfWeek - (int)CultureInfo.CurrentCulture.DateTimeFormat.FirstDayOfWeek; //sunday=always0, monday=always1, etc.

        //As a result we need to have day 0,1,2,3,4,5,6 
        if (diff < 0)
        {
            diff += 7;
        }
        return diff + 1; //Make it 1..7
    }
}
user324365
  • 89
  • 7
1

The following method should return the DateTime that you want. Pass in true for Sunday being the first day of the week, false for Monday:

private DateTime getStartOfWeek(bool useSunday)
{
    DateTime now = DateTime.Now;
    int dayOfWeek = (int)now.DayOfWeek;

    if(!useSunday)
        dayOfWeek--;

    if(dayOfWeek < 0)
    {// day of week is Sunday and we want to use Monday as the start of the week
    // Sunday is now the seventh day of the week
        dayOfWeek = 6;
    }

    return now.AddDays(-1 * (double)dayOfWeek);
}
firedfly
  • 2,299
  • 2
  • 22
  • 20
1

You could use the excellent Umbrella library:

using nVentive.Umbrella.Extensions.Calendar;
DateTime beginning = DateTime.Now.BeginningOfWeek();

However, they do seem to have stored Monday as the first day of the week (see the property nVentive.Umbrella.Extensions.Calendar.DefaultDateTimeCalendarExtensions.WeekBeginsOn), so that previous localized solution is a bit better. Unfortunate.

Edit: looking closer at the question, it looks like Umbrella might actually work for that too:

// Or DateTime.Now.PreviousDay(DayOfWeek.Monday)
DateTime monday = DateTime.Now.PreviousMonday(); 
DateTime sunday = DateTime.Now.PreviousSunday();

Although it's worth noting that if you ask for the previous Monday on a Monday, it'll give you seven days back. But this is also true if you use BeginningOfWeek, which seems like a bug :(.

Domenic
  • 110,262
  • 41
  • 219
  • 271
1

Following on from Compile This' answer, use the following method to obtain the date for any day of the week:

public static DateTime GetDayOfWeek(DateTime dateTime, DayOfWeek dayOfWeek)
{
   var monday = dateTime.Date.AddDays((7 + (dateTime.DayOfWeek - DayOfWeek.Monday) % 7) * -1);

   var diff = dayOfWeek - DayOfWeek.Monday;

   if (diff == -1)
   {
      diff = 6;
   }

   return monday.AddDays(diff);
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Rowan Richards
  • 401
  • 8
  • 20
  • This implementation does not work as expected, at least under german culture. For example: dateTime="2022-08-10", dayOfWeek="Monday" it returns "2022-08-01" instead of "2022-08-08". – daniol Sep 14 '22 at 14:13
0

This will return both the beginning of the week and the end of the week dates:

    private string[] GetWeekRange(DateTime dateToCheck)
    {
        string[] result = new string[2];
        TimeSpan duration = new TimeSpan(0, 0, 0, 0); //One day 
        DateTime dateRangeBegin = dateToCheck;
        DateTime dateRangeEnd = DateTime.Today.Add(duration);

        dateRangeBegin = dateToCheck.AddDays(-(int)dateToCheck.DayOfWeek);
        dateRangeEnd = dateToCheck.AddDays(6 - (int)dateToCheck.DayOfWeek);

        result[0] = dateRangeBegin.Date.ToString();
        result[1] = dateRangeEnd.Date.ToString();
        return result;

    }

I have posted the complete code for calculating the begin/end of week, month, quarter and year on my blog ZamirsBlog

iCollect.it Ltd
  • 92,391
  • 25
  • 181
  • 202
Zamir
  • 1
0

Here is a combination of a few of the answers. It uses an extension method that allows the culture to be passed in. If one is not passed in, the current culture is used. This will give it maximum flexibility and reuse.

/// <summary>
/// Gets the date of the first day of the week for the date.
/// </summary>
/// <param name="date">The date to be used</param>
/// <param name="cultureInfo">If none is provided, the current culture is used</param>
/// <returns>The date of the beggining of the week based on the culture specifed</returns>
public static DateTime StartOfWeek(this DateTime date, CultureInfo cultureInfo=null) =>
    date.AddDays(-1 * (7 + (date.DayOfWeek - (cultureInfo ?? CultureInfo.CurrentCulture).DateTimeFormat.FirstDayOfWeek)) % 7).Date;

Example Usage:

public static void TestFirstDayOfWeekExtension() {
    DateTime date = DateTime.Now;
    foreach(System.Globalization.CultureInfo culture in CultureInfo.GetCultures(CultureTypes.UserCustomCulture | CultureTypes.SpecificCultures)) {
        Console.WriteLine($"{culture.EnglishName}: {date.ToShortDateString()} First Day of week: {date.StartOfWeek(culture).ToShortDateString()}");
    }
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Mike
  • 1,525
  • 1
  • 14
  • 11
0

If you want Saturday or Sunday or any day of week, but not exceeding the current week (Sat-Sun), I got you covered with this piece of code.

public static DateTime GetDateInCurrentWeek(this DateTime date, DayOfWeek day)
{
    var temp = date;
    var limit = (int)date.DayOfWeek;
    var returnDate = DateTime.MinValue;

    if (date.DayOfWeek == day) 
        return date;

    for (int i = limit; i < 6; i++)
    {
        temp = temp.AddDays(1);

        if (day == temp.DayOfWeek)
        {
            returnDate = temp;
            break;
        }
    }
    if (returnDate == DateTime.MinValue)
    {
        for (int i = limit; i > -1; i++)
        {
            date = date.AddDays(-1);

            if (day == date.DayOfWeek)
            {
                returnDate = date;
                break;
            }
        }
    }
    return returnDate;
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Ali Umair
  • 1,386
  • 1
  • 21
  • 42
0

We like one-liners: Get the difference between the current culture's first day of week and the current day, and then subtract the number of days from the current day:

var weekStartDate = DateTime.Now.AddDays(-((int)now.DayOfWeek - (int)DateTimeFormatInfo.CurrentInfo.FirstDayOfWeek));
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
0

Calculating this way lets you choose which day of the week indicates the start of a new week (in the example I chose Monday).

Note that doing this calculation for a day that is a Monday will give the current Monday and not the previous one.

//Replace with whatever input date you want
DateTime inputDate = DateTime.Now;

//For this example, weeks start on Monday
int startOfWeek = (int)DayOfWeek.Monday;

//Calculate the number of days it has been since the start of the week
int daysSinceStartOfWeek = ((int)inputDate.DayOfWeek + 7 - startOfWeek) % 7;

DateTime previousStartOfWeek = inputDate.AddDays(-daysSinceStartOfWeek);
C. Keats
  • 81
  • 8
0

I work with a lot of schools, so correctly using Monday as the first day of the week is important here.

A lot of the most terse answers here don't work on Sunday -- we often end up returning the date of tomorrow on Sunday, which is not good for running a report on last week's activities.

Here's my solution, which returns last Monday on Sunday, and today on Monday.

// Adding 7 so remainder is always positive; Otherwise % returns -1 on Sunday.
var daysToSubtract = (7 + (int)today.DayOfWeek - (int)DayOfWeek.Monday) % 7;

var monday = today
    .AddDays(-daysToSubtract)
    .Date;

Remember to use a method parameter for "today" so it's unit testable!!

Display Name
  • 133
  • 1
  • 7
-1
    namespace DateTimeExample
    {
        using System;

        public static class DateTimeExtension
        {
            public static DateTime GetMonday(this DateTime time)
            {
                if (time.DayOfWeek != DayOfWeek.Monday)
                    return GetMonday(time.AddDays(-1)); //Recursive call

                return time;
            }
        }

        internal class Program
        {
            private static void Main()
            {
                Console.WriteLine(DateTime.Now.GetMonday());
                Console.ReadLine();
            }
        }
    } 
Denis
  • 833
  • 3
  • 12
  • 22
  • 1
    Can you expand your answer to include an explanation of your code? It helps the reader more than you might think. – gunr2171 Oct 02 '14 at 19:22
  • 1
    Using recursion is a very poor implementation. Just because you could use recursions doesn't mean you should. It would be slower and more memory intensive than other solutions provided here. – mikecamimo Aug 30 '17 at 22:45
-1

I did it like this:

DateTime.Now.Date.AddDays(-(DateTime.Now.Date.DayOfWeek == 0 ? 7 : (int)DateTime.Now.Date.DayOfWeek) + 1)

All this code does is subtracting a number of days from the given datetime.

If day of week is 0(sunday) then subtract 7 else subtract the day of the week.

Then add 1 day to the result of the previous line, which gives you the monday of that date.

This way you can play around with the number(1) at the end to get the desired day.

private static DateTime GetDay(DateTime date, int daysAmount = 1)
{
    return date.Date.AddDays(-(date.Date.DayOfWeek == 0 ? 7 : (int)date.Date.DayOfWeek) + daysAmount);
}

If you really want to use the DayOfWeek enum then something like this can be used... though I presonally prefer the above one, as I can add or subtract any amount of days.

private static DateTime GetDayOfWeek(DateTime date, DayOfWeek dayOfWeek = DayOfWeek.Monday)
{
    return date.Date.AddDays(-(date.Date.DayOfWeek == 0 ? 7 : (int)date.Date.DayOfWeek) + (dayOfWeek == 0 ? 7 : (int)dayOfWeek));
}
Noob
  • 710
  • 11
  • 15
-2
public static System.DateTime getstartweek()
{
    System.DateTime dt = System.DateTime.Now;
    System.DayOfWeek dmon = System.DayOfWeek.Monday;
    int span = dt.DayOfWeek - dmon;
    dt = dt.AddDays(-span);
    return dt;
}
stealthyninja
  • 10,343
  • 11
  • 51
  • 59
-2
   d = DateTime.Now;
            int dayofweek =(int) d.DayOfWeek;
            if (dayofweek != 0)
            {
                d = d.AddDays(1 - dayofweek);
            }
            else { d = d.AddDays(-6); }
Adrian
  • 1