Find day of the week of the first day of January from the date of Easter

Asked

Viewed 1,681 times

1

I have a college assignment in which I must build a calendar on C from the date of Easter of a given year. I can find the date of Easter and correctly build the calendar in ASCII art, but I can’t find the day of the week of January 1st.

On this Wikipedia page(in English) is written:

The basic approximation of all methods consists of finding an 'anchor date': a known pair (e.g.: 1 January 1800, a Wednesday), determining the amount of days between the anchor date and the date you want to find, and using module 7 (%7 or mod 7) to find the code for the new day of the week.

I decided to apply this concept in my program, the snippet was like this:

if(mes_pascoa == 3)
    dia_semana = (dia_pascoa + bissexto + 28 + 31) % 7;
else if(mes_pascoa == 4)
    dia_semana = (dia_pascoa + bissexto + 31 + 28 + 31) % 7;

But the value of the day of the week is incorrect, even with the correct implementation of the code. For example, for mes_pascoa = 3 and dia_pascoa = 31 which was Easter in the year 2013 so bissexto = 0, the value of dia_semana should be 2, since January 1, 2013 fell on a Tuesday. However, my snippet is returning 6 to dia_semana.

My question is, is there an error in my code or in this concept that I used? I would also love to know if there is any other C code implementation that can help me.

3 answers

1

The sums must be subtract. If from an Easter Sunday you want to "walk backwards", for the 1st of January ... subtract!

if(mes_pascoa == 3)
    dia_semana = (dia_pascoa - bissexto - 28 - 31) % 7;
else if(mes_pascoa == 4)
    dia_semana = (dia_pascoa - bissexto - 31 - 28 - 31) % 7;

Some implementations make 'strange' modules when there are negative numbers. I would add a large enough value to the calculation to avoid negative numbers.

if(mes_pascoa == 3)
    dia_semana = ((dia_pascoa - bissexto - 28 - 31) + 700) % 7;
else if(mes_pascoa == 4)
    dia_semana = ((dia_pascoa - bissexto - 31 - 28 - 31) + 700) % 7;
  • I was doubtful in this, even to calculate the 'distance' between two dates, can the concept of progress and regression be applied? That wouldn’t give me a negative day count in case of setback?

  • Yeah, it’ll be a negative date. I have no problem with negative date ... 0 April 2015 corresponds to 31 March ... -4 May 2015 corresponds to 26 April

  • Still January 1 is not correct, for the year 2013 it falls on a Sunday. I’m beginning to think that the problem is in the concept...

  • 31 - 0 - 28 - 31 is -28, and 700 - 28 gives 672. 672 % 7 is 0. E 31 % 7 is 3

  • You have to take the days of the current month. For April 20 (2014), the account is 20 - 20 - 0 - 31 - 28 - 31 + 1

1


It seems to me that this concept on the Wikipedia page itself is incorrect or was misinterpreted by me, but I found a solution that suits me very well:

To reach the 1st of January from any date, you must calculate the number of days between the two dates and make module 7. The result will give the day of the first Sunday of the month. We must subtract this result from 8 to get the day of the week of January 1. For example:

For 2013, the distance between the date of Easter (31/3) and January 1 is 90 days. The module of 90 by 7 is 6 (therefore, 6/1 was a Sunday). We should now go back 5 units of the 7 possible day "codes" of the week (with 0 being Sunday on January 1 and 7 being Sunday after the first week of the month), or 6 days of the 8 available between the first and second week. With this, we get code 2, which represents Tuesday.

In code it can be represented as follows:

#include <stdio.h>
/* Descobridor de 1º de Janeiro a partir da data da páscoa */
typedef struct{
    int dia, mes, ano, cod_semana;
} Data;

Data dia_janeiro(Data data){
    Data d; 
    int ano = data.ano, bissexto = 0;
    while(ano % 100 == 0)
        ano /= 100;
    if(ano % 4 == 0)
        bissexto = 1;

    d.dia = 1;
    d.mes = 1;
    d.ano = data.ano;

    if(data.mes == 3)
        d.cod_semana = 8 - ((data.dia + 28 + 31 + bissexto) % 7);
    else if(data.mes == 4)
        d.cod_semana = 8 - ((data.dia + 31 + 28 + 31 + bissexto) % 7);
    if(d.cod_semana > 6) d.cod_semana -= 7;
    return d;
}

int main(){
    Data pascoa;
    pascoa.dia = 31;
    pascoa.mes = 3;
    pascoa.ano = 2013;
    printf("Código do 1º de Janeiro: %d.\n", dia_janeiro(pascoa).cod_semana);
    return 0;
}

Change pascoa.dia, pascoa.mes and pascoa.ano for any valid values of an Easter date and you will have the day of the week in January 1 code of the respective year.

1

How about we skip Easter and use the C library?

#include <stdio.h>
#include <time.h>

int main(void) {
    const char *ds[] = {"Domingo", "Segunda", "Terca",
                        "Quarta", "Quinta", "Sexta", "Sabado"};
    struct tm tm = {0};
    tm.tm_mday = 1;
    tm.tm_mon = 0; // Janeiro
    tm.tm_year = 113; // 2013
    tm.tm_isdst = 0;
    mktime(&tm); // normalizar tm
    printf("1 de Janeiro de %d calhou em %s.\n",
          tm.tm_year + 1900, ds[tm.tm_wday]);
    return 0;
}

You can see the code working on ideone.

  • I would love to use other @pmg libraries, but the work says you should build the calendar from the date of Easter.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.