# Thursday, August 20, 2009

Some useful DateTime extensions

I’m doing some work where a user can select data based on choice like “This week” and “Last month”. I wrote a bunch of extension methods that are pretty generic and may be useful for others.

Here is is:

public static class DateTimeExtensions
{
    /// <summary>
    /// Return the date that is the start of the week relative to the specified date.
    /// </summary>
    /// <param name="date"></param>
    /// <returns></returns>
    public static DateTime GetStartOfWeek(this DateTime date)
    {
        DayOfWeek day = date.DayOfWeek;
        int days = day – CultureInfo.CurrentCulture.DateTimeFormat.FirstDayOfWeek;
        DateTime start = date.AddDays(-days);
        return start.Date;
    }

    /// <summary>
    /// Return the date that is the start of the week relative to the specified date.
    /// </summary>
    /// <param name="date"></param>
    /// <returns></returns>
    public static DateTime GetStartOfLastWeek(this DateTime date)
    {
        return date.GetStartOfWeek().AddDays(-7);
    }

    /// <summary>
    /// Return the date that is the end of the week relative to the specified date.
    /// </summary>
    /// <param name="date"></param>
    /// <returns></returns>
    public static DateTime GetEndOfWeek(this DateTime date)
    {
        return date.GetStartOfWeek().AddDays(6);
    }

    /// <summary>
    /// Return the date that is the end of the week relative to the specified date.
    /// </summary>
    /// <param name="date"></param>
    /// <returns></returns>
    public static DateTime GetEndOfLastWeek(this DateTime date)
    {
        return date.GetEndOfWeek().AddDays(-7);
    }

    /// <summary>
    /// Return the date that is the start of the month relative to the specified date.
    /// </summary>
    /// <param name="date"></param>
    /// <returns></returns>
    public static DateTime GetStartOfMonth(this DateTime date)
    {
        return new DateTime(date.Year, date.Month, 1);
    }

    /// <summary>
    /// Return the date that is the start of previous month relative to the specified date.
    /// </summary>
    /// <param name="date"></param>
    /// <returns></returns>
    public static DateTime GetStartOfLastMonth(this DateTime date)
    {
        return date.GetStartOfMonth().AddMonths(-1);
    }

    /// <summary>
    /// Return the date that is the end of the month relative to the specified date.
    /// </summary>
    /// <param name="date"></param>
    /// <returns></returns>
    public static DateTime GetEndOfMonth(this DateTime date)
    {
        return new DateTime(date.Year, date.Month, date.GetDaysInMonth(), 23, 59, 59, 999);
    }

    /// <summary>
    /// Return the date that is the start of previous month relative to the specified date.
    /// </summary>
    /// <param name="date"></param>
    /// <returns></returns>
    public static DateTime GetEndOfLastMonth(this DateTime date)
    {
        return date.GetStartOfLastMonth().GetEndOfMonth();
    }

    /// <summary>
    /// Returns the number of days in the month of the specified date.
    /// </summary>
    /// <param name="date"></param>
    /// <returns></returns>
    public static int GetDaysInMonth(this DateTime date)
    {
        return DateTime.DaysInMonth(date.Year, date.Month);
    }

    /// <summary>
    /// Return the first day of the year relative to the specified date.
    /// </summary>
    /// <param name="date"></param>
    /// <returns></returns>
    public static DateTime GetStartOfYear(this DateTime date)
    {
        return new DateTime(date.Year, 1, 1);
    }

    /// <summary>
    /// Return the first day of the last year relative to the specified date.
    /// </summary>
    /// <param name="date"></param>
    /// <returns></returns>
    public static DateTime GetStartOfLastYear(this DateTime date)
    {
        return new DateTime(date.Year - 1, 1, 1);
    }

    /// <summary>
    /// Return the last day of the year relative to the specified date.
    /// </summary>
    /// <param name="date"></param>
    /// <returns></returns>
    public static DateTime GetEndOfYear(this DateTime date)
    {
        return new DateTime(date.Year, 12, 31, 23, 59, 59, 999);
    }

    /// <summary>
    /// Return the last day of the last year relative to the specified date.
    /// </summary>
    /// <param name="date"></param>
    /// <returns></returns>
    public static DateTime GetEndOfLastYear(this DateTime date)
    {
        return new DateTime(date.Year - 1, 12, 31, 23, 59, 59, 999);
    }

}
#    Comments [7] |
Saturday, October 03, 2009 7:51:59 AM (Eastern Daylight Time, UTC-04:00)
Was looking for exactly this !
Thanks :)
Saturday, October 03, 2009 7:53:49 AM (Eastern Daylight Time, UTC-04:00)
Btw, Any chance you have unit tests for this ?
Saturday, October 03, 2009 9:02:05 AM (Eastern Daylight Time, UTC-04:00)
Sorry. No unittests :-)
Saturday, October 03, 2009 5:54:41 PM (Eastern Daylight Time, UTC-04:00)
Bit of a bug with GetStartOfWeek. You should use DateTime.Today instead of DateTime.Now.
Sunday, October 04, 2009 6:51:01 PM (Eastern Daylight Time, UTC-04:00)
Also, I ran into an issue when computing GetStartOfWeek and today is a sunday. I modified the method to use Sunday as the start of the week, rather than Monday and that fixed things. Otherwise, if you want to use Monday, you'll need to change your logic to account for the fact that DayOfWeek.Sunday = 0 and DayofWeek.Monday = 1.
Thursday, October 08, 2009 12:47:43 PM (Eastern Daylight Time, UTC-04:00)
I would bet that the original author of these extensions lives or works in a country that does start their week on Monday, as most European countries do.

To make the extensions internationalized, you must incorporate CultureInfo.CurrentCulture.DateTimeFormat.FirstDayOfWeek into the calculations.

So, the updated method would be:
/// <summary>
/// Return the date that is the start of the week relative to the specified date.
/// </summary>
/// <param name="date"></param>
/// <returns></returns>
public static DateTime StartOfWeek(this DateTime date)
{
DayOfWeek day = date.DayOfWeek;
int days = day - CultureInfo.CurrentCulture.DateTimeFormat.FirstDayOfWeek;
DateTime start = DateTime.Today.AddDays(-days);
return start.Date;
}

There is one more additional problem with this method, the description says relative to the specified date, but it is actually trying to make it relative to TODAY, and if today is not the date passed in, it's getting it wrong for today too.

So the final version of this method would be:
public static DateTime StartOfWeek(this DateTime date)
{
DayOfWeek day = date.DayOfWeek;
int days = day - CultureInfo.CurrentCulture.DateTimeFormat.FirstDayOfWeek;
DateTime start = date.AddDays(-days);
return start.Date;
}
Thursday, October 08, 2009 2:37:00 PM (Eastern Daylight Time, UTC-04:00)
Hi Todd,

Thanks for the improvements! The DateTime.Today.AddDays(-days) was a serious bug!?
I've updated the post :-)

Cheers,
Mark
Comments are closed.