12

I'm trying to make a calendar using wpf. By using itemsPanel and more, I have a grid with 7 columns(sunday-saturday) and 6 rows(week# of month). If i can find the starting position of the first of each month by getting the weekday and week number(of the month), how can I find the week number(0-5 of each month)? Also can't I somehow just fill in the calendar from there? I'm lost and I don't know what else to try.

public partial class SchedulePage : Page
{        
    MainWindow _parentForm;
    public int dayofweek;

    public SchedulePage(MainWindow parentForm)
    {
        InitializeComponent();
        _parentForm = parentForm;
        // DateTime date = new DateTime(year, month, day);

        _parentForm.bindings = new BindingCamper();          
        _parentForm.bindings.schedule.Add(new Schedule { WeekNo = (int) getWeekNumber(), WeekDay = dayofweek });
        DataContext = _parentForm.bindings;
        // lblTest.Content = dates(2011, 10, 27);
    }

    public double getWeekNumber()
    {
        dayofweek = getWeekDay(2011, 10, 31);
        double h = dayofweek / 7;
        double g = Math.Floor(h);
        return g;
    }

    public int getWeekDay(int year, int month, int day)
    {
        //year = 2011;
        //month = 10;
        //day = 27;
        int[] t = { 0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4 };
        // year -= month < 3;
        return (year + year / 4 - year / 100 + year / 400 + t[month - 1] + day) % 7;
    }
LPL
  • 16,827
  • 6
  • 51
  • 95
TMan
  • 4,044
  • 18
  • 63
  • 117

3 Answers3

17

You must use Calendar.GetDayOfWeek and Calendar.GetWeekOfYear in preference to writing yourself.

You can guarantee that if you write any date / time handling code yourself it will contain faults and won't work in different locales.

public class Row
{
    public string MonthWeek { get; set; }
    public string Year { get; set; }
    public string Month { get; set; }
    public string Day { get; set; }
    public string WeekOfYear { get; set; }
}

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        var l = new List<Row>();
        DateTime startDate = DateTime.Now;
        DateTime d = new DateTime(startDate.Year, startDate.Month, 1);
        var cal = System.Globalization.DateTimeFormatInfo.CurrentInfo.Calendar;
        var ms = cal.GetWeekOfYear(new DateTime(d.Year, d.Month, 1), System.Globalization.CalendarWeekRule.FirstDay, System.DayOfWeek.Sunday);
        for (var i = 1; d.Month == startDate.Month; d = d.AddDays(1))
        {
            var si = new Row();
            var month_week = (d.Day / 7) + 1;
            si.MonthWeek = month_week.ToString();
            si.Month = d.Year.ToString();
            si.Year = d.Month.ToString();
            si.Day = d.Day.ToString();
            si.WeekOfYear = cal.GetWeekOfYear(d, System.Globalization.CalendarWeekRule.FirstDay, DayOfWeek.Sunday).ToString();
            l.Add(si);
        }
        dataGrid1.ItemsSource = l;
    }
}

together with the obligatory DataGrid in the XAML:

    <DataGrid AutoGenerateColumns="true" Name="dataGrid1" />
Richard Harrison
  • 19,247
  • 4
  • 40
  • 67
  • So this would return what week that date is in 1-53, how do I take that info and use it though b/c my grid has 6 rows grid.row 0-5. Sorry for the ignorance this is all new to me. In other words the coloumns is what week day and row is week#. I don't know how to apply that to the grid and fill it all in – TMan Oct 27 '11 at 17:42
  • thanks, what is var ms and i used for, they are never used for anything? – TMan Oct 27 '11 at 22:38
  • ms is the week number of the month start. i isn't used - as it is effectively always going to be the same as month day. – Richard Harrison Oct 28 '11 at 09:59
11

You can use Calendar.GetWeekOfYear from Globalization to do this.

Here's the MSDN docs for it: http://msdn.microsoft.com/en-us/library/system.globalization.calendar.getweekofyear.aspx

You should pass the appropriate culture properties from CultureInfo.CurrentCulture to GetWeekOfYear so that you match the current culture properly.

Example:

int GetWeekOfYear(DateTime date)
{
    return Calendar.GetWeekOfYear(
        date,
        CultureInfo.CurrentCulture.DateTimeFormat.CalendarWeekRule,
        CultureInfo.CurrentCulture.DateTimeFormat.FirstDayOfWeek
    );
}

You could easily modify this into an extension method on DateTime:

static int GetWeekOfYear(this DateTime date)
{
    return Calendar.GetWeekOfYear(
        date,
        CultureInfo.CurrentCulture.DateTimeFormat.CalendarWeekRule,
        CultureInfo.CurrentCulture.DateTimeFormat.FirstDayOfWeek
    );
}
Rytis I
  • 1,105
  • 8
  • 19
Polynomial
  • 27,674
  • 12
  • 80
  • 107
  • +1 - but I'd say "must use" rather than "can use" - ref my answer – Richard Harrison Oct 27 '11 at 16:57
  • I would caution you against how much you rely on that method - it will give you inconsistent results. For example, Dec 30 2012 is a Sunday. If you call that method with a WeekRule of FirstDay or FirstFourDayWeek and Sunday as the first day of week, it will return 53. However, if you call that method with a date of Jan 1, 2013 which is part of the same week you will get 1. – AndrewS Oct 27 '11 at 17:31
  • So this would return what week that date is in 1-53, how do I take that info and use it though b/c my grid has 6 rows grid.row 0-5. Sorry for the ignorance this is all new to me. – TMan Oct 27 '11 at 17:34
  • In other words the coloumns is what week day and row is week#. I don't know how to apply that to the grid and fill it all in. – TMan Oct 27 '11 at 17:36
  • @AndrewS that doesn't seem inconsistent it seems to be right given the input data as it is the week number relative to the start of the year - there can't be an absolute week number that is consistent across year boundaries IMHO – Richard Harrison Oct 27 '11 at 18:10
  • @Richard Yes I suppose they are considering the year of the date you are providing but then you must still be careful about how you invoke this. If you look at something like Outlook when it is showing week numbers, it would have shown 1 for the line in the date navigator or month view containing the 30th and 31 of Dec 2012 whereas that method would have returned 53. Personally I would consider those days to be part of the first week of 2013 but then they would probably need to return a year out param or something. – AndrewS Oct 27 '11 at 18:21
  • You should use `CultureInfo.CurrentCulture.DateTimeFormat.FirstDayOfWeek` for the parameter, so that you stick to the current culture. Updated answer to reflect this. – Polynomial Oct 27 '11 at 19:35
  • System.Globalization.Calendar.GetWeekOfYear is a non-static method. The instance under DateTimeFormatInfo.CurrentInfo could be used as shown [here](https://msdn.microsoft.com/en-us/library/system.globalization.calendar.getweekofyear(v=vs.110).aspx). I updated the answer to reflect this. – Marco Lackovic Sep 23 '15 at 11:27
0

With @Polynomial answer, I have this error:

An object reference is required for the non-static field, method, or property...

If you instanciate GregorianCalendar before then you can call the method GetWeekOfYear !

private static int GetWeekNumber(DateTime time)
{
    GregorianCalendar cal = new GregorianCalendar();
    int week = cal.GetWeekOfYear(time, CalendarWeekRule.FirstFullWeek, DayOfWeek.Monday);
    return week;
}
A. Morel
  • 9,210
  • 4
  • 56
  • 45