How to know the week of a given month?

7

I'm working on ASP.NET MVC 4, and I want to know what the week is for a given month.

For example, the user wants to define a frequency of occurrences, and as such says:

  • The occurrence will occur every%% weeks%;
  • The occurrence will happen this week on Monday and Thursday;

When obtaining this user data, I have to generate a list of dates with this data. The result of the list will look something like:

2 - corresponds to the Monday of the second week of February;

03/02/2014 - corresponds to the Thursday of the second week of February;

06/02/2014 - corresponds to the Monday of the fourth week of February;

17/02/2014 - corresponds to the Thursday of the fourth week of February;

20/02/2014 - corresponds to the Monday of the first week of March;

03/03/2014 - corresponds to the Thursday of the first week of March;

... Out there

As such I want to try to know how to calculate / know the weeks of the month (I think the solution happens to know the number of the week in the year), and still the day of the week that week.

    
asked by anonymous 04.02.2014 / 16:35

3 answers

4

I wrote this algorithm

  • Calculates the first day of the current week (in my example, the first day of the week and 'Sunday').
  • Calculates the Monday and Thursday of this week, and adds to the 'list
  • Go 2 weeks, and go back to step 2
  • Input data

    • weekCount : total number of weeks to be examined
    • skipWeeks : number of weeks to skip / skip forward. In your example where "The occurrence will happen every 2 weeks", skipWeeks would be 1. That is, the algorithm will examine a week, advance 1 week, examine the week, advance 1 week, etc.
    • daysOfWeek : days of the week (ex: new[] {DayOfWeek.Monday, DayOfWeek.Thursday} )
    • (optional) startDate : day to start the search. By default this is the current day.
    public IEnumerable<DateTime> AgendarAlertas(int weekCount, int skipWeeks, IEnumerable<DayOfWeek> daysOfWeek )
    {
        return AgendarAlertas(weekCount, skipWeeks, daysOfWeek, DateTime.Today);
    }
    
    public IEnumerable<DateTime> AgendarAlertas(int weekCount, int skipWeeks, IEnumerable<DayOfWeek> daysOfWeek , DateTime startDate)
    {
        var dates = new List<DateTime>();
    
        Calendar calendar = new GregorianCalendar();
        DateTime firstDayOfWeek = DateTime.Today.StartOfWeek(DayOfWeek.Sunday);
    
        for (int currentWeek = 0; currentWeek < weekCount; currentWeek++)
        {
            //calcular dias da semana
            dates.AddRange(
                daysOfWeek.Select(dayOfWeek =>
                                    firstDayOfWeek.NextDayOfWeek(dayOfWeek)));
    
            //avancar "skipWeeks"
            firstDayOfWeek = calendar.AddWeeks(firstDayOfWeek, skipWeeks + 1);
            currentWeek += skipWeeks;
        }
    
        //filtrar dias passados
        return dates.SkipWhile(date => date < startDate);
    }
    

    2 extension methods

    public static class DateTimeExtensions
    {
        public static DateTime NextDayOfWeek(this DateTime dt, DayOfWeek day)
        {
            int diff = day - dt.DayOfWeek;
    
            //se o dia ja passou, calcular o da proxima semana
            if (diff < 0)
                diff += 7;
    
            return dt.AddDays(diff).Date;
        }
    
        public static DateTime StartOfWeek(this DateTime dt, DayOfWeek startOfWeek)
        {
            int diff = dt.DayOfWeek - startOfWeek;
            if (diff < 0)
                diff += 7;
    
            return dt.AddDays(-1 * diff).Date;
        }
    }
    

    Result:

    AgendarAlertas(11, 1, new[] {DayOfWeek.Thursday, DayOfWeek.Friday});
    
    06/02/2014 00:00:00 //proxima quinta-feira
    07/02/2014 00:00:00 //proxima sexta-feira
    20/02/2014 00:00:00 //proxima quinta-feira + 2 semanas
    21/02/2014 00:00:00 //proxima sexta-feira  + 2 semanas
    06/03/2014 00:00:00 //proxima quinta-feira + 4 semanas
    07/03/2014 00:00:00 //proxima sexta-feira  + 4 semanas
    20/03/2014 00:00:00 //proxima quinta-feira + 6 semanas
    21/03/2014 00:00:00 //proxima sexta-feira  + 6 semanas
    03/04/2014 00:00:00 //proxima quinta-feira + 8 semanas
    04/04/2014 00:00:00 //proxima sexta-feira  + 8 semanas
    17/04/2014 00:00:00 //proxima quinta-feira + 10 semanas
    18/04/2014 00:00:00 //proxima sexta-feira  + 10 semanas
    
        
    04.02.2014 / 17:06
    3

    Option 1:

    public static void obterDiasComIntervaloSemanal(DateTime data, int intervalo, int total_semanas, DayOfWeek[] dias)
    {
        int semana_atual = 1;    
        while (semana_atual <= total_semanas)
        {
            if (dias.Contains(data.DayOfWeek) && semana_atual % intervalo == 0)
                Console.WriteLine(data.ToString("dd/MM/yyyy")); // Aqui você decide o quer fazer se quiser adicionar numa lista de datas a data atual...
            if (data.DayOfWeek.Equals(DayOfWeek.Sunday))
                semana_atual++;
            data = data.AddDays(1);
        }
    }
    

    And to use:

    static void Main(string[] args)
    {
        DayOfWeek[] dias = {
                           DayOfWeek.Monday,
                           DayOfWeek.Thursday
                       };
        obterDiasComIntervaloSemanal(new DateTime(2014, 02, 01), 2, 10, dias);
    }
    

    Result:

    Option 2:

    public static DateTime getDateInterval(int year, int month, int week, DayOfWeek day)
    {
        int current_week = 1;
        var days = DateTime.DaysInMonth(year, month);
    
        DateTime date = new DateTime(year, month, 1);
    
        for (int i = 1; i <= days; i++)
        {
            if (date.DayOfWeek == day && current_week == week)
                break;
            if (date.DayOfWeek.Equals(DayOfWeek.Sunday))
                current_week++;
            date = date.AddDays(1);
        }
    
        return date;
    }
    

    To use:

    static void Main(string[] args)
    {
                               // year month week   day of week
        var data1 = getDateInterval(2014, 2, 2, DayOfWeek.Monday); // 03/02/2014
        var data2 = getDateInterval(2014, 2, 2, DayOfWeek.Thursday); // 06/02/2014
        var data3 = getDateInterval(2014, 2, 4, DayOfWeek.Monday); // 17/02/2014
    }
    
        
    04.02.2014 / 17:25
    1

    Solving your problem in the simplest way: one for iterating directly over dates.

    It looks like this:

    var date = new DateTime(2014, 2, 4);
    var intervaloSemanas = 2;
    var diasDaSemana = new DayOfWeek[] { DayOfWeek.Monday, DayOfWeek.Thursday, };
    
    var dataDeStop = date.AddDays(80);
    var incremento = TimeSpan.FromDays(7 * intervaloSemanas);
    
    for (var dt = date.AddDays(-(int)date.DayOfWeek);
         dt <= dataDeStop;
         dt += incremento)
    {
        foreach (var dayOfWeek in diasDaSemana)
            Console.WriteLine("{0:yyyy'-'MM'-'dd}", dt.AddDays((int)dayOfWeek));
    }
    

    Output:

    This code is also very fast because it goes straight on the dates you want.

        
    05.02.2014 / 14:03