286

I want to get the first day and last day of the month where a given date lies in. The date comes from a value in a UI field.

If I'm using a time picker I could say

var maxDay = dtpAttendance.MaxDate.Day;

But I'm trying to get it from a DateTime object. So if I have this...

DateTime dt = DateTime.today;

How to get first day and last day of the month from dt?

CAD
  • 4,112
  • 6
  • 29
  • 47
  • It's not clear what you're asking. There's a single value stored in the `_Date` variable. What "min and max" are you trying to get from that value? – David Jun 16 '14 at 14:04
  • it is getting downvoted because people are wondering why you would want to do such a think and where you would use such a thing. You are not telling us anything about your initial issue here – Mo Patel Jun 16 '14 at 14:08
  • It is better to ask **what u want to do?** not like that **How you want to do?** may other use can suggest you correctly. – Shell Jun 16 '14 at 14:09
  • 2
    @Chathuranga u know what will be the minimum date of the any month.... but the question is what is last date of current month.. u can get like this.. add 1 month in current date and minus 1 day from that date.. now u will get last date of ur current month – Shell Jun 16 '14 at 14:11

18 Answers18

646

DateTime structure stores only one value, not range of values. MinValue and MaxValue are static fields, which hold range of possible values for instances of DateTime structure. These fields are static and do not relate to particular instance of DateTime. They relate to DateTime type itself.

Suggested reading: static (C# Reference)

UPDATE: Getting month range:

DateTime date = ...
var firstDayOfMonth = new DateTime(date.Year, date.Month, 1);
var lastDayOfMonth = firstDayOfMonth.AddMonths(1).AddDays(-1);

UPDATE: From comments (@KarlGjertsen & @SergeyBerezovskiy)

DateTime date = ...
var firstDayOfMonth = new DateTime(date.Year, date.Month, 1);
var lastDayOfMonth = firstDayOfMonth.AddMonths(1).AddSeconds(-1);
//OR
var lastDayOfMonth = firstDayOfMonth.AddMonths(1).AddTicks(-1);
Sachin
  • 2,152
  • 1
  • 21
  • 43
Sergey Berezovskiy
  • 232,247
  • 41
  • 429
  • 459
  • 36
    I know I'm being picky here, but shouldn't `lastDayofMonth` be `firstDayOfMonth.AddMonths(1).AddSeconds(-1);`? – Karl Gjertsen Jan 05 '16 at 15:27
  • 63
    @KarlGjertsen you are not picky enough :) Perfect solution will be `AddTicks(-1)`, but if we don't care about time part and think only about date part, then days work fine – Sergey Berezovskiy Jan 06 '16 at 10:17
  • 8
    Now that is being picky! ;-) The question doesn't say how the values are going to be used, so I tend to code defensively. – Karl Gjertsen Jan 06 '16 at 13:27
  • @SergeyBerezovskiy I'd hate to raise this point but don't you lose the timezone information when you new up a DateTime like this? Whatever timezone info was attached to the original DateTime instance is lost when you make a new instance like this. – Marko Mar 26 '17 at 14:29
  • @Marko DateTimes don't carry time zone information. That's what TimeZoneInfo is for. DateTimes only have the Kind property (Local, UTC, Unspecified) to identify the type of time it is. You could also use DateTimeOffset, but that only carries the offset from UTC, not the specific time zone. – Bacon Bits Dec 19 '17 at 14:23
  • 3
    @KarlGjertsen, you want to see picky... I personally do `< firstDayOfNextMonth` instead of `<= lastDayOfMonth`. That way it'll always work regardless of the granularity. (I'm sure ticks will be fine, but who know what the future brings... nanoticks?) – adam0101 Sep 12 '19 at 22:14
150

This is more a long comment on @Sergey and @Steffen's answers. Having written similar code myself in the past I decided to check what was most performant while remembering that clarity is important too.

Result

Here is an example test run result for 10 million iterations:

2257 ms for FirstDayOfMonth_AddMethod()
2406 ms for FirstDayOfMonth_NewMethod()
6342 ms for LastDayOfMonth_AddMethod()
4037 ms for LastDayOfMonth_AddMethodWithDaysInMonth()
4160 ms for LastDayOfMonth_NewMethod()
4212 ms for LastDayOfMonth_NewMethodWithReuseOfExtMethod()
2491 ms for LastDayOfMonth_SpecialCase()

Code

I used LINQPad 4 (in C# Program mode) to run the tests with compiler optimization turned on. Here is the tested code factored as Extension methods for clarity and convenience:

public static class DateTimeDayOfMonthExtensions
{
    public static DateTime FirstDayOfMonth_AddMethod(this DateTime value)
    {
        return value.Date.AddDays(1 - value.Day);
    }
    
    public static DateTime FirstDayOfMonth_NewMethod(this DateTime value)
    {
        return new DateTime(value.Year, value.Month, 1);
    }
    
    public static DateTime LastDayOfMonth_AddMethod(this DateTime value)
    {
        return value.FirstDayOfMonth_AddMethod().AddMonths(1).AddDays(-1);
    }
    
    public static DateTime LastDayOfMonth_AddMethodWithDaysInMonth(this DateTime value)
    {
        return value.Date.AddDays(DateTime.DaysInMonth(value.Year, value.Month) - value.Day);
    }
    
    public static DateTime LastDayOfMonth_SpecialCase(this DateTime value)
    {
        return value.AddDays(DateTime.DaysInMonth(value.Year, value.Month) - 1);
    }
    
    public static int DaysInMonth(this DateTime value)
    {
        return DateTime.DaysInMonth(value.Year, value.Month);
    }
    
    public static DateTime LastDayOfMonth_NewMethod(this DateTime value)
    {
        return new DateTime(value.Year, value.Month, DateTime.DaysInMonth(value.Year, value.Month));
    }

    public static DateTime LastDayOfMonth_NewMethodWithReuseOfExtMethod(this DateTime value)
    {
        return new DateTime(value.Year, value.Month, value.DaysInMonth());
    }
}

void Main()
{
    Random rnd = new Random();
    DateTime[] sampleData = new DateTime[10000000];
    
    for(int i = 0; i < sampleData.Length; i++) {
        sampleData[i] = new DateTime(1970, 1, 1).AddDays(rnd.Next(0, 365 * 50));
    }
    
    GC.Collect();
    System.Diagnostics.Stopwatch sw = System.Diagnostics.Stopwatch.StartNew();
    for(int i = 0; i < sampleData.Length; i++) {
        DateTime test = sampleData[i].FirstDayOfMonth_AddMethod();
    }
    string.Format("{0} ms for FirstDayOfMonth_AddMethod()", sw.ElapsedMilliseconds).Dump();
    
    GC.Collect();
    sw.Restart();
    for(int i = 0; i < sampleData.Length; i++) {
        DateTime test = sampleData[i].FirstDayOfMonth_NewMethod();
    }
    string.Format("{0} ms for FirstDayOfMonth_NewMethod()", sw.ElapsedMilliseconds).Dump();
    
    GC.Collect();
    sw.Restart();
    for(int i = 0; i < sampleData.Length; i++) {
        DateTime test = sampleData[i].LastDayOfMonth_AddMethod();
    }
    string.Format("{0} ms for LastDayOfMonth_AddMethod()", sw.ElapsedMilliseconds).Dump();

    GC.Collect();
    sw.Restart();
    for(int i = 0; i < sampleData.Length; i++) {
        DateTime test = sampleData[i].LastDayOfMonth_AddMethodWithDaysInMonth();
    }
    string.Format("{0} ms for LastDayOfMonth_AddMethodWithDaysInMonth()", sw.ElapsedMilliseconds).Dump();

    GC.Collect();
    sw.Restart();
    for(int i = 0; i < sampleData.Length; i++) {
        DateTime test = sampleData[i].LastDayOfMonth_NewMethod();
    }
    string.Format("{0} ms for LastDayOfMonth_NewMethod()", sw.ElapsedMilliseconds).Dump();

    GC.Collect();
    sw.Restart();
    for(int i = 0; i < sampleData.Length; i++) {
        DateTime test = sampleData[i].LastDayOfMonth_NewMethodWithReuseOfExtMethod();
    }
    string.Format("{0} ms for LastDayOfMonth_NewMethodWithReuseOfExtMethod()", sw.ElapsedMilliseconds).Dump();

    for(int i = 0; i < sampleData.Length; i++) {
        sampleData[i] = sampleData[i].FirstDayOfMonth_AddMethod();
    }
    
    GC.Collect();
    sw.Restart();
    for(int i = 0; i < sampleData.Length; i++) {
        DateTime test = sampleData[i].LastDayOfMonth_SpecialCase();
    }
    string.Format("{0} ms for LastDayOfMonth_SpecialCase()", sw.ElapsedMilliseconds).Dump();
    
}

Analysis

I was surprised by some of these results.

Although there is not much in it the FirstDayOfMonth_AddMethod was slightly faster than FirstDayOfMonth_NewMethod in most runs of the test. However, I think the latter has a slightly clearer intent and so I have a preference for that.

LastDayOfMonth_AddMethod was a clear loser against LastDayOfMonth_AddMethodWithDaysInMonth, LastDayOfMonth_NewMethod and LastDayOfMonth_NewMethodWithReuseOfExtMethod. Between the fastest three there is nothing much in it and so it comes down to your personal preference. I choose the clarity of LastDayOfMonth_NewMethodWithReuseOfExtMethod with its reuse of another useful extension method. IMHO its intent is clearer and I am willing to accept the small performance cost.

LastDayOfMonth_SpecialCase assumes you are providing the first of the month in the special case where you may have already calculated that date and it uses the add method with DateTime.DaysInMonth to get the result. This is faster than the other versions, as you would expect, but unless you are in a desperate need for speed I don't see the point of having this special case in your arsenal.

Conclusion

Here is an extension method class with my choices and in general agreement with @Steffen I believe:

public static class DateTimeDayOfMonthExtensions
{
    public static DateTime FirstDayOfMonth(this DateTime value)
    {
        return new DateTime(value.Year, value.Month, 1);
    }
    
    public static int DaysInMonth(this DateTime value)
    {
        return DateTime.DaysInMonth(value.Year, value.Month);
    }
    
    public static DateTime LastDayOfMonth(this DateTime value)
    {
        return new DateTime(value.Year, value.Month, value.DaysInMonth());
    }
}

If you have got this far, thank you for time! Its been fun :¬). Please comment if you have any other suggestions for these algorithms.

BurnsBA
  • 4,347
  • 27
  • 39
WooWaaBob
  • 3,397
  • 3
  • 23
  • 23
  • 7
    You have way too less credit for your effort though. It's useful! – Dion V. Nov 06 '15 at 12:02
  • 2
    Thanks @DionV. - it is nice to be appreciated! Short answers are great when you are in a hurry but I think some deeper analysis to follow is often useful. – WooWaaBob Nov 09 '15 at 09:29
  • You missed another alternative: `LastDayOfMonth_AddMethod_SpecialCase` (or something like that). Expecting the first day of the month as parameter, I think the quickest should be what `LastDayOfMonth_AddMethod` does! So that would be as simple as: `return value.AddMonths(1).AddDays(-1);` – Andrew Jul 01 '16 at 02:15
  • 1
    Thanks @Andrew and here are my results using that: 2835 ms for LastDayOfMonth_SpecialCase(), and; 4685 ms for LastDayOfMonth_AddMethod_SpecialCase(). Which probably makes sense when considering struct creation time and that the internal representation of DateTime probably makes adding days a simple operation but adding months a more complex algorithm. – WooWaaBob Jul 04 '16 at 15:11
24

Getting month range with .Net API (just another way):

DateTime date = ...
var firstDayOfMonth = new DateTime(date.Year, date.Month, 1);
var lastDayOfMonth = new DateTime(date.Year, date.Month, DateTime.DaysInMonth(date.Year, date.Month));
Steffen Mangold
  • 1,184
  • 1
  • 20
  • 39
10

"Last day of month" is actually "First day of *next* month, minus 1". So here's what I use, no need for "DaysInMonth" method:

public static DateTime FirstDayOfMonth(this DateTime value)
{
    return new DateTime(value.Year, value.Month, 1);
}

public static DateTime LastDayOfMonth(this DateTime value)
{
    return value.FirstDayOfMonth()
        .AddMonths(1)
        .AddMinutes(-1);
}

NOTE: The reason I use AddMinutes(-1), not AddDays(-1) here is because usually you need these date functions for reporting for some date-period, and when you build a report for a period, the "end date" should actually be something like Oct 31 2015 23:59:59 so your report works correctly - including all the data from last day of month.

I.e. you actually get the "last moment of the month" here. Not Last day.

OK, I'm going to shut up now.

jazzcat
  • 4,351
  • 5
  • 36
  • 37
5
DateTime dCalcDate = DateTime.Now;
dtpFromEffDate.Value = new DateTime(dCalcDate.Year, dCalcDate.Month, 1);
dptToEffDate.Value = new DateTime(dCalcDate.Year, dCalcDate.Month, DateTime.DaysInMonth(dCalcDate.Year, dCalcDate.Month));
Soner Gönül
  • 97,193
  • 102
  • 206
  • 364
sphaze
  • 59
  • 1
  • 1
  • Generally avoid code-only answers. Consider adding a `description` that helps to explain your code. Thanks –  Mar 26 '15 at 01:17
3

Here you can add one month for the first day of current month than delete 1 day from that day.

DateTime now = DateTime.Now;
var startDate = new DateTime(now.Year, now.Month, 1);
var endDate = startDate.AddMonths(1).AddDays(-1);
Mykola
  • 3,343
  • 6
  • 23
  • 39
Chiragkumar Thakar
  • 3,616
  • 5
  • 37
  • 49
3

If you only care about the date

var firstDay = new DateTime(date.Year, date.Month, 1, 0, 0, 0, date.Kind);
var lastDay = new DateTime(date.Year, date.Month, 1, 0, 0, 0, date.Kind).AddMonths(1).AddDays(-1);

If you want to preserve time

var firstDay = new DateTime(date.Year, date.Month, 1, date.Hour, date.Minute, date.Second, date.Kind);
var lastDay = new DateTime(date.Year, date.Month, 1, date.Hour, date.Minute, date.Second, date.Kind).AddMonths(1).AddDays(-1);
Vitaly
  • 2,064
  • 19
  • 23
  • It's gonna completely fail in december dudeeeeeee. it'll try to create datetime with month "13" and throw exception that there is no such date. – Pawel Dec 04 '17 at 12:30
  • Since when December is 13? There are total 12 months. What calendar do you use? – Vitaly Dec 04 '17 at 16:38
  • If your date is december then it'll try to add one month which will result in exception. new DateTime(date.Year, 12+ 1, 1, 0, 0, 0, date.Kind).AddDays(-1); Substracting one day from it will be done after datetime will be created so for december it'll fail when trying date for month "13". You can try it. – Pawel Dec 05 '17 at 07:58
2

Try this one:

string strDate = DateTime.Now.ToString("MM/01/yyyy");
marai
  • 865
  • 1
  • 11
  • 16
1

The accepted answer here does not take into account the Kind of the DateTime instance. For example if your original DateTime instance was a UTC Kind then by making a new DateTime instance you will be making an Unknown Kind instance which will then be treated as local time based on server settings. Therefore the more proper way to get the first and last date of the month would be this:

var now = DateTime.UtcNow;
var first = now.Date.AddDays(-(now.Date.Day - 1));
var last = first.AddMonths(1).AddTicks(-1);

This way the original Kind of the DateTime instance is preserved.

Marko
  • 12,543
  • 10
  • 48
  • 58
1

For Persian culture

PersianCalendar pc = new PersianCalendar();            

var today = pc.GetDayOfMonth(DateTime.Now);
var firstDayOfMonth = pc.GetDayOfMonth(DateTime.Now.AddDays(-(today-1)));
var lastDayOfMonth = pc.GetDayOfMonth(DateTime.Now.AddMonths(1).AddDays(-today));            
Console.WriteLine("First day "+ firstDayOfMonth);
Console.WriteLine("Last day " + lastDayOfMonth);
st4hoo
  • 2,196
  • 17
  • 25
Mohammad Daliri
  • 1,370
  • 6
  • 20
  • 43
1

I used this in my script(works for me) but I needed a full date without the need of trimming it to only the date and no time.

public DateTime GetLastDayOfTheMonth()
{
    int daysFromNow = DateTime.DaysInMonth(DateTime.Now.Year, DateTime.Now.Month) - (int)DateTime.Now.Day;
    return DateTime.Now.AddDays(daysFromNow);
}
st4hoo
  • 2,196
  • 17
  • 25
1

You can do it

DateTime dt = DateTime.Now; 
DateTime firstDayOfMonth = new DateTime(dt.Year, date.Month, 1);
DateTime lastDayOfMonth = firstDayOfMonth.AddMonths(1).AddDays(-1);
1

Give this a try. It basically calculates the number of days that has passed on DateTime.Now, then subtracts one from that and uses the new value to find the first of the current month. From there it uses that DateTime and uses .AddMonths(-1) to get the first of the previous month.

Getting the last day of last month does basically the same thing except it adds one to number of days in the month and subtracts that value from DateTime.Now.AddDays, giving you the last day of the previous month.

int NumberofDays = DateTime.Now.Day;
int FirstDay = NumberofDays - 1;
int LastDay = NumberofDays + 1;
DateTime FirstofThisMonth = DateTime.Now.AddDays(-FirstDay);
DateTime LastDayOfLastMonth = DateTime.Now.AddDays(-LastDay);
DateTime CheckLastMonth = FirstofThisMonth.AddMonths(-1);
Tanveer Badar
  • 5,438
  • 2
  • 27
  • 32
1

You can try this for get current month first day;

DateTime.Now.AddDays(-(DateTime.Now.Day-1))

and assign it a value.

Like this:

dateEndEdit.EditValue = DateTime.Now;
dateStartEdit.EditValue = DateTime.Now.AddDays(-(DateTime.Now.Day-1));
Mahir Uslu
  • 21
  • 4
0

Create an instance of DateTime class

DateTime dateTime = DateTime.Now;

If you want to get the last day of the month you can do this

int lastDayOfMonth = DateTime.DaysInMonth(caducidadPuntos.Year, caducidadPuntos.Month);

If you want to get the first day of the month, you can do this

DateTime firstDayMonth = new DateTime(dateTime.Year, dateTime.Month, 1);
Arkox
  • 51
  • 2
0

We had the requirement of being able to get the start and end of a given dates month, including times, inclusively. We ended up utilizing the aforementioned solutions, huge thanks to everyone here, and combined it into a util class to be able to get the start and end for a given month and year number combination up to the last millisecond. Including what we moved forward with in the event it helps someone else.

The util:

public class DateUtil
{
    public static (DateTime startOfMonth, DateTime endOfMonth) GetStartAndEndOfMonth(int month, int year)
    {
        DateTime startOfMonth = GetStartOfMonth(month, year);
        DateTime endOfMonth = GetEndOfMonth(month, year);

        return (startOfMonth, endOfMonth);
    }

    public static DateTime GetStartOfMonth(int month, int year)
    {
        return new DateTime(year, month, 1).Date;
    }

    public static DateTime GetEndOfMonth(int month, int year)
    {
        return new DateTime(year, month, 1).Date.AddMonths(1).AddMilliseconds(-1);
    }
}

Usage:

(DateTime startOfMonth, DateTime endOfMonth) = DateUtil.GetStartAndEndOfMonth(2, 2021); // February, 2021
Matthias Müller
  • 444
  • 6
  • 15
Thomas
  • 550
  • 5
  • 17
-1

easy way to do it

Begin = new DateTime(DateTime.Now.Year, DateTime.Now.Month,1).ToShortDateString();
End = new DataFim.Text = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.DaysInMonth(DateTime.Now.Year, DateTime.Now.Month)).ToShortDateString();
-1
DateTime dCalcDate = DateTime.Now;
var startDate = new DateTime(Convert.ToInt32(Year), Convert.ToInt32(Month), 1);
var endDate = new DateTime(Convert.ToInt32(Year), Convert.ToInt32(Month), DateTime.DaysInMonth((Convert.ToInt32(Year)), Convert.ToInt32(Month)));
giser_yugang
  • 6,058
  • 4
  • 21
  • 44