tags:

views:

84

answers:

2

So I have an application that needs to get a date focus so it can run appropriately. Given a particular date to focus on it needs to know what week it is in. I'm calculating weeks based on Monday dates. And I'm wondering if my focus on Mondays is excessive.

public static DateTime PreviousMonday(this DateTime dt)
{
    var dateDayOfWeek = (int)dt.DayOfWeek;
    if (dateDayOfWeek==0)
    {
        dateDayOfWeek = dateDayOfWeek + 7; 
    }
    var alterNumber = dateDayOfWeek - ((dateDayOfWeek*2)-1);

    return dt.AddDays(alterNumber);
}

/// <summary>
/// Personal tax week starts on the first Monday after the week with 6th April in unless 6th April is a Monday in 
/// which case that starts the first week. In a leap year this means you can have a week 53 which due to the mod 4 approach of calculating 
/// flexi week means you get a 5 week flexi period.
/// As such this method forces the weeks into the range 1 - 52 by finding the week number for the week containing 6th April and
/// the number for the current week. Treating the 6th April week as week 1 and using the difference to calculate the tax week.
/// </summary>
public static int GetTaxWeek(this DateTime dt)
{
    var startTaxYear = GetActualWeekNumber(new DateTime(DateTime.Now.Year, 4, 6));
    var thisWeekNumber = GetActualWeekNumber(dt);
    var difference = thisWeekNumber - startTaxYear;
    return difference < 0 ? 53 + difference : difference + 1;
}

private static int GetActualWeekNumber(DateTime dt)
{
    var ci = System.Threading.Thread.CurrentThread.CurrentCulture;
    var cal = ci.Calendar;
    var calWeekRule = ci.DateTimeFormat.CalendarWeekRule;
    var fDoW = ci.DateTimeFormat.FirstDayOfWeek;
    return cal.GetWeekOfYear(dt, calWeekRule, fDoW);
}

public static int PeriodWeek(this DateTime dt)
{
    var rawPeriodWeek = GetTaxWeek(dt) % 4;
    return rawPeriodWeek == 3 ? 1 : rawPeriodWeek + 2;
}

}

The system runs a rolling 4 week schedule starting in the first tax week and needs to behave differently depending on where in the schedule it is. So you can see...

  1. Get a date from a user (say userDate)
  2. Call userDate=userDate.PreviousMonday(); to get to the Monday of the week given - where Sunday is the week end
  3. Call userDate.PeriodWeek(); and get the Period you are in from 1 to 4.

GetTaxWeek is public because it is used elsewhere... I also replace the date as it is used more than once and I don't want to have to remember to change it more than once.

Can I see the wood for the trees? Or is there a more error free way of doing this.

+6  A: 

I think you can greatly simplify your code using the GregorianCalendar inside System.Globalization. Here you can get the week number for a given date like this:

GregorianCalendar gc = new GregorianCalendar(); 
int weekno = gc.GetWeekOfYear(date, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday);

You see here that you can give the rules for how to caclulate the week number according to your local rules. Like here in Norway, we have Monday as our first week day, and the first week of the year is the first week that has four or more days. Set this to your culture specific rules to get the correct week numbers.

Some of your specific handling you still ahve to do by hand, but some of the clutter can be removed using this at least :)

Øyvind Bråthen
A: 

why are you not using a DateTimePicker control? it will tell you the day for the user selected date. Then you can simply subtract no. of days from it to get date for monday. For example: I'm using a DateTimePicker control and named it dtpTemp. the event used is

dtpTemp_ValueChanged()

dtpTemp.Value.DayOfWeek - will give you the day: tuesday, wednesday, thursday etc.

then you can use following code with switch case accordingly:

dtpTemp.Value.AddDays(num); to get date for monday

here num will have -ve values which will depend on day calculated above. Values: -1 for tuesday, -2 for wednesday, -3 for thursday and so on.

plus, using a datetimepicker will also have a positive impact on the UI itself.

Anurag
This is a console app which runs focussed on DateTime.Now unless an argument is passed in with a parse-able date. Also, (int)DayOfWeek.Sunday always returns 0 so you need to remember to catch that case in whatever algorith you use to get num.
Paul D'Ambra