152
votes

I can't think of an easy one or two liner that would get the previous months first day and last day.

I am LINQ-ifying a survey web app, and they squeezed a new requirement in.

The survey must include all of the service requests for the previous month. So if it is April 15th, I need all of Marches request ids.

var RequestIds = (from r in rdc.request 
                  where r.dteCreated >= LastMonthsFirstDate && 
                  r.dteCreated <= LastMonthsLastDate 
                  select r.intRequestId);

I just can't think of the dates easily without a switch. Unless I'm blind and overlooking an internal method of doing it.

10

10 Answers

330
votes
var today = DateTime.Today;
var month = new DateTime(today.Year, today.Month, 1);       
var first = month.AddMonths(-1);
var last = month.AddDays(-1);

In-line them if you really need one or two lines.

25
votes

The way I've done this in the past is first get the first day of this month

dFirstDayOfThisMonth = DateTime.Today.AddDays( - ( DateTime.Today.Day - 1 ) );

Then subtract a day to get end of last month

dLastDayOfLastMonth = dFirstDayOfThisMonth.AddDays (-1);

Then subtract a month to get first day of previous month

dFirstDayOfLastMonth = dFirstDayOfThisMonth.AddMonths(-1);
12
votes

using Fluent DateTime https://github.com/FluentDateTime/FluentDateTime

        var lastMonth = 1.Months().Ago().Date;
        var firstDayOfMonth = lastMonth.FirstDayOfMonth();
        var lastDayOfMonth = lastMonth.LastDayOfMonth();
9
votes
DateTime LastMonthLastDate = DateTime.Today.AddDays(0 - DateTime.Today.Day);
DateTime LastMonthFirstDate = LastMonthLastDate.AddDays(1 - LastMonthLastDate.Day);
6
votes

I use this simple one-liner:

public static DateTime GetLastDayOfPreviousMonth(this DateTime date)
{
    return date.AddDays(-date.Day);
}

Be aware, that it retains the time.

4
votes

An approach using extension methods:

class Program
{
    static void Main(string[] args)
    {
        DateTime t = DateTime.Now;

        DateTime p = t.PreviousMonthFirstDay();
        Console.WriteLine( p.ToShortDateString() );

        p = t.PreviousMonthLastDay();
        Console.WriteLine( p.ToShortDateString() );


        Console.ReadKey();
    }
}


public static class Helpers
{
    public static DateTime PreviousMonthFirstDay( this DateTime currentDate )
    {
        DateTime d = currentDate.PreviousMonthLastDay();

        return new DateTime( d.Year, d.Month, 1 );
    }

    public static DateTime PreviousMonthLastDay( this DateTime currentDate )
    {
        return new DateTime( currentDate.Year, currentDate.Month, 1 ).AddDays( -1 );
    }
}

See this link http://www.codeplex.com/fluentdatetime for some inspired DateTime extensions.

3
votes

The canonical use case in e-commerce is credit card expiration dates, MM/yy. Subtract one second instead of one day. Otherwise the card will appear expired for the entire last day of the expiration month.

DateTime expiration = DateTime.Parse("07/2013");
DateTime endOfTheMonthExpiration = new DateTime(
  expiration.Year, expiration.Month, 1).AddMonths(1).AddSeconds(-1);
1
votes

If there's any chance that your datetimes aren't strict calendar dates, you should consider using enddate exclusion comparisons... This will prevent you from missing any requests created during the date of Jan 31.

DateTime now = DateTime.Now;
DateTime thisMonth = new DateTime(now.Year, now.Month, 1);
DateTime lastMonth = thisMonth.AddMonths(-1);

var RequestIds = rdc.request
  .Where(r => lastMonth <= r.dteCreated)
  .Where(r => r.dteCreated < thisMonth)
  .Select(r => r.intRequestId);
1
votes
DateTime now = DateTime.Now;
int prevMonth = now.AddMonths(-1).Month;
int year = now.AddMonths(-1).Year;
int daysInPrevMonth = DateTime.DaysInMonth(year, prevMonth);
DateTime firstDayPrevMonth = new DateTime(year, prevMonth, 1);
DateTime lastDayPrevMonth = new DateTime(year, prevMonth, daysInPrevMonth);
Console.WriteLine("{0} {1}", firstDayPrevMonth.ToShortDateString(),
  lastDayPrevMonth.ToShortDateString());
1
votes

This is a take on Mike W's answer:

internal static DateTime GetPreviousMonth(bool returnLastDayOfMonth)
{
    DateTime firstDayOfThisMonth = DateTime.Today.AddDays( - ( DateTime.Today.Day - 1 ) );
    DateTime lastDayOfLastMonth = firstDayOfThisMonth.AddDays (-1);
    if (returnLastDayOfMonth) return lastDayOfLastMonth;
    return firstDayOfThisMonth.AddMonths(-1);
}

You can call it like so:

dateTimePickerFrom.Value = GetPreviousMonth(false);
dateTimePickerTo.Value = GetPreviousMonth(true);