Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations IamaSherpa on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

help me with a calendar

Status
Not open for further replies.

40744145142

Technical User
Jul 20, 2006
15
RO
I just started to do a calendar in Pascal. I did it, but now i want to make it better, and i need a tip to make an algorithm to find out the first day of the month. And i don't know how. Now, i found that kind of calendar in TC, and i want to inspire from that progam. And i found this: "first_day=find_day(a, mm, yy)". What does it mean? And eventually how i could write this code in pascal? Thanks in advance.
 
I'm not familar with Turbo C. It's very old. Since you didn't specify wether first_day, a, mm, and yy are integers, characters, or strings, I will have to guess.

I've seen different methods used. One was for C code for a calendar that used that function. yy was the year, mm was the month number, a was the date. The function then returned was day of the week the date was. Sunday = 0, Monday = 1, etc.

In some pascal code I saw, the function used characters instead of integers. It returned a charcter the repesented the day.

Can you give us more info on how first_day is used?


James P. Cottingham
-----------------------------------------
I'm number 1,229!
I'm number 1,229!
 
There is no function included in TC call first_day or find_day; I would guess that it either was part of a toolkit or something the original programmer wrote himself.
As an exercise in problem solving, why don't you try and solve the problem on your own? As A hint, convert the date to a julian date; plenty of algorithms out there to that, and it simplifies the math. Just looking at your post right now I could think of 2 - 3 approaches that I would try, if it were my project.

The simplest solution is the best!
 
So, Prattaratt, i've tried to make this by myself, but i couldn't. I don't want to make this calendar in julian, i want it in gregorian date. I would try something like this: if the year is 2, i will add 365+the days 'till the month that you typed, and something like this, but i can't write it in an algorithm. Please help me with some hints. And thanx both of you for thying to help me.
 
2ffat, that code from sourcecodesworld.com is that one that i asked in my thread. I didn't understand what this section is doing : "first_day=find_day(1, mm, yy)". If you know, please help me to understand. Thanx.
 
The function find_day() will return the day of the week for the given date. According to the orginal program, 0 = Sunday and 6 = Saturday so the function will return an integer that will coorespond to a number between 0 and 6.

The original program drew a calendar on screen after you entered in a month and year. It always passed 1 as the day in order to know what day (Sunday through Saturday) to start the calendar on.

I have included the functions in question along with my comments.
Code:
find_day(int dd, int mm, int yy)
{
    // dd = day in question, used in odddayday function
    // mm = month in question, used in odddaymonth function
    // yy = year in question, used in odddayyear and isleapyear functions

    int odddays, leapyear;
    // odddays is the value returned
    // leapyear = 1 if yy is leap year, 0 if not

    leapyear=isleapyear(yy);

    // Adds oddyear + oddmonth + oddday
    odddays=odddayyear(yy)+odddaymonth(mm,leapyear)+odddayday(dd);

    // Get modulus of return day divived by 7
    odddays %= 7;

    return odddays;
}


/*Every 4th year is a leap year, however centuries are not leap years
except those divisible by 400
for example:
1990 is NOT a leap year
2000 is a leap year
2004 is a leap year
*/
isleapyear(int yy)
{
        if(yy%4==0 && (yy%100!=0 || yy%400==0))
                return 1; // leap year
        else
                return 0; // not leap year
}

//Calculates odd days upto first day of year
odddayyear(int yy)
{
    // odddays is return value
    int odddays=0;

    // subtract 1 from year
    yy-=1;

    // if year > than 400
    if(yy>=400)
        yy%=400; // Get the modulus of year / 400

    // if year (or modulus) is greater or equal to 100
    if(yy>=100)
    {
        odddays=yy/100; // return value is year / 100
        odddays *= 5; // return value is multipled by 5
        yy%=100; // get modulus of year or year modulus
    }

    odddays += yy; // add return value to year or year modulus
    odddays += yy/4; // add return value to year / 4

    return odddays;
}

odddaymonth(int mm, char leapyear)
{
    // mm is month
    // leapyear = 0 or 1, see above. Note C++ treats char as int
    switch(mm)
    {
        // January returns 0
        case 1:
            return 0;

        // February returns 3
        case 2:
            return 3;

        // March and November returns 4 if leap year or 3 if not
        case 3:
        case 11:
            return leapyear?4:3;

        // April and July return 0 if leap year or 6 if not
        case 4:
        case 7:
            return leapyear?0:6;

        // May returns 2 if leap year or 1 is not
        case 5:
            return leapyear?2:1;

        // June returns 5 if leap year of 4 if not
        case 6:
            return leapyear?5:4;

        // August returns 3 if leap year or 2 is not
        case 8:
            return leapyear?3:2;

        // September and December returns 6 if leap year or 5 if not
        case 9:
        case 12:
            return leapyear?6:5;

        // October returns 1 if leap year or 0 if not
        case 10:
            return leapyear?1:0;
    }
}

// return remainder of day divided by 7
odddayday(int dd)
{
   // dd is day
   return dd%7;
}

/*******************H I N T S *********************
Every 4th year is a leap year,
however centuries are not leap years except those divisible by 400
for example:
1990 is NOT a leap year
2000 is a leap year
2004 is a leap year

for example:
-------------

1 ordinary year = 365 days = (52 weeks + 1 day) = 1 odd day
                that's why if this year 23th August is on Tuesday,
it will be on Wednesday next year

1 leap year      = 366 days = (52 weeks + 2 days) = 2 odd days
100 years        =        76 ordinary years     +        24 leap years
               = [(76*52) weeks+76 days] + [(24*52) weeks+48 days]
               = 5200 weeks + 124 days
               = 5217 weeks + 5 days
               = 5 odd days
200 years        = 10 odd days = 3 odd days
300 years        = 15 odd days = 1 odd days
400 years        = 20 + 1 odd days = 0 days

800 years        = 0 odd days

Sunday is the 0th odd day, Monday the 1st odd day and so on*/

Let's take today's date as an example: 3 August 2006
isleapyear(2006) will return 0 since 2006 is not evenly divisable by 4 and (100 or 400). Therefore it is NOT a leap year.

odddayyear(2006) will return 6.

odddaymonth(8, 0) will return 2.

odddayday(3) will return 3.

Thus odddays = 11 in this case. Finally odddays % 7 will return 4 or Thursday.

James P. Cottingham
-----------------------------------------
I'm number 1,229!
I'm number 1,229!
 
Ok, 2ffat, understood, but now comes the big question: How the heck i will "translate" this "first_day ()" function in pascal??
 
It's been so long since I've used Pascal I don't remember much. If should be pretty straight forward. Simple math and case statements.

In C++ the term odddays *=5 would become odddays := odddays * 5 in pascal. Similarly leapyear?1:0 would become an "if" statement in pascal.

James P. Cottingham
-----------------------------------------
I'm number 1,229!
I'm number 1,229!
 
What I Don't know is how i translate firs_day() function in pascal, not the odddays*=.....
 
So, if you could explain me with your own words, how it orks the algorithm for finding out the first day of the month. This is what i need. An explanation for the algorithm which finds out the first day of your month. For example, for August 2006, how works the algorithm which is showing you the first day of the month, in our case, for august 2006, which is on tuesday.
 
OK, once more. The function int first_day(int dd, int mm, int yy) takes three integer, dd, mm, and yy and returns an integer. So to find out what day 8 August 2006 is, you would put in:
Code:
int first_day = find_day(3, 8, 2006);

Inside the function, you have:
Code:
int odddays, leapyear;
leapyear=isleapyear(yy);
odddays=odddayyear(yy)+odddaymonth(mm,leapyear)+odddayday(dd);
odddays %= 7;
return odddays;

This function calls 4 other functions, int isleapyear(int yy), int odddayyear(int yy), int odddaymonth(int mm, int leapyear), and int odddayday(int dd).

The function int isleapyear(int yy) takes an integer and returns an integer. This function is fairly straight forward.

It looks at the integer sent to it and decides if the integer is evenly divisiable by 4 (with the modlus function yy%4==0) AND if the integer is evenly divisable by 100 OR 400 ((yy%100!=0 || yy%400==0)). If this case is true then the function returns 1, meaning the year is a leap year. Otherwise, it returns 0, meaning the year is not a leap year.

In our case, isleapyear(2006) returns 0 since 2006 mod 4 is 2.

The function int odddayyear(int yy) is the most complex function in this snippet. It takes an integer and returns an integer. I'll show this step by step.

Code:
odddayyear(int yy)
{
    // yy will be 2006
    int odddays=0;

    // subtract 1 from year
    yy-=1; // yy will now be 2005

    // This will be true since 2006 > 400
    if(yy>=400)
        yy%=400; // yy now equals 5

    // This condition is false since yy  < 100
    if(yy>=100)
    {
        odddays=yy/100; // return value is year / 100
        odddays *= 5; // return value is multipled by 5
        yy%=100; // get modulus of year or year modulus
    }

    odddays += yy; // odddays equals 5
    odddays += yy/4; // oddays now equals 6 as 5 / 4 = 1.25 and since odddays is an integer it drops the .25 so we have 1 + 5 = 6

    return odddays; // This function returns 6;
}

So now odddayyears(2006) returns a 6.

Next is int oddaymonth(int mm, char leapyear). C++ treats characters as integers so this function is equvalent to int oddaymonth(int mm, int leapyear). This function also takes two integers (or one integer and one charater) and returns an integer. This function is simply a case statement.

It takes the month number (mm) and the leapyear (1 or 0) and decides what to return based upon which month it is and if it is a leap year or not. In our case, mm = 8 and leapyear = 0 so the case statement 8 executes return leapyear?3:2. Since leapyear is 0, the function returns 2. Had it been a leap year, it would have been 3.

So odddaymonths(8, 0) returns a 2.

Next we have int odddayday(int dd) which also takes an integer and returns an integer. This function simply mods the number with 7. So odddayday(3) returns 3.

At this point in the function odddays = 6 + 2 + 3 or 11.

Finally, odddays is "modded" with 7. So 11 mod 7 = 4

Since Sunday is 0, we count Monday = 1, Tuesday = 2, Wednesday = 3, and Thursday = 4. So 3 August 2006 is a Thursday.


James P. Cottingham
-----------------------------------------
I'm number 1,229!
I'm number 1,229!
 
The odddays function is finding the odddays until the given year? What is doing the odddayyear function? And why is substracting one year from the given year? Why at the end of odddayyear function we are adding at the odddays function this: yy/4? What is doing the odddaymonth function??? And why in case of august it returns 2 or 3 (leapyear)? And what is doing the odddayday function?? These are my biggest questions.
 
2ffat, thank you for the efforts you made with me, now i will study those two links. Thank you very much for helping me in these days. I will announce you if i'll make this calendar. Bye, bye
 
Now, I have an idea for resolving my problem, but i don't now which was the first day of January, 1st year??? I have found many days, but i don't know which is the real one, if you know which is the correct first day of January the fisrt year, please tell me.
 
This is not a "valid" question! The reason is that the calendar has been changed several times during the change of time and thus you must compensate by altering the calender and the change date is also different depending upon country and such.

On the last calenderchange from Julian to Gregorian there were removed 10 days due to the skew in the calender. This applied to the countries changing at that wery time, othaer that changed at a later day had to compensate more days.

So it's not possible to answer the question as the week might not even have 7 days in those days.

So there is really no answer to that question.

I do have a calender calculating routine (in C):
/*****************************************
* Calender.h *
* Time & date calculations *
* (C) Icecap 2005-02-11 *
* All calculations is based on Gregorian calender & ISO notation *
*****************************************/
enum {_Monday = 1, _Tuesday, _Wednesday, _Thursday, _Friday, _Saturday,_Sunday} Weekdays;
enum {_JANUARY = 1,_FEBUARY,_MARCH,_APRIL,_MAY,_JUNE,_JULY,_AUGUST,_SEPTEMBER,_OCTOBER,_NOVEMBER,_DECEMBER};
const unsigned char _WEEK_Days_In_Month[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
enum {Year_Outa_Range = 0x80,Month_Outa_Range,Date_Outa_Range} Date_Errors;

char isDTS(unsigned int year,unsigned char month,unsigned char date,unsigned char hour)
{
// Returns true when Daylight Time Saving (DTS) is valid
unsigned char x;
switch(month)
{
case _JANUARY:
case _FEBUARY:
case _MARCH:
case _NOVEMBER:
case _DECEMBER: return(0);
case _MAY:
case _JUNE:
case _JULY:
case _AUGUST:
case _SEPTEMBER: return(1);
case _APRIL: /* From first Sunday in April */
x = Day_Of_Week(year,_APRIL,1);
if((x > date) || ((x == date) && (hour > 2))) return(1);
else return(0);
case _OCTOBER: /* To last Sunday in October */
x = _WEEK_Days_In_Month[_OCTOBER] - (7 - Day_Of_Week(year,_OCTOBER,_WEEK_Days_In_Month[_OCTOBER]));
if((x < date) || ((x == date) && (hour < 2))) return(1);
else return(0);
}
return(0);
}

int Is_Leapyear(unsigned int year)
{
return(!((year % 100) & 3) && ((year % 100) || !((year / 100) & 3)));
}

unsigned char Invalid_Date(unsigned int year,unsigned char month,unsigned char date)
{
if((year < 1753) || (year > 9999)) return(Year_Outa_Range);
if((month < 1) || (month > 12)) return(Month_Outa_Range);
if((date < 1) || (date > (_WEEK_Days_In_Month[month] + ((month == 2) && Is_Leapyear(year))))) return(Date_Outa_Range);
return(false);
}

unsigned char Day_Of_Week(unsigned int year,unsigned char month,unsigned char date)
{ /* 1=Monday, 2=tuesday etc. as ISO declares */
int Result;
Result = Invalid_Date(year,month,date);
if(Result) return(Result);
if(month < 3)
{
month += 10;
year--;
}
else month -= 2;
Result = 2 + (((((26 * (int) month - 2) / 10) + (int) date + (year % 100) + ((year % 100) / 4) + ((year / 100) / 4) - (2 * (year / 100))) + 4));
while(Result < 0) Result += 7;
Result %= 7;
Result++; /* Make it go 1-7 in stead of 0-6 */
return(Result);
}

Totte
Keep making it perfect and it will end up broken.
 
I have made this.I have figured out with the help of the links given by 2ffat, the calendar. Prattaratt, you were right when you said that the simplest solution is the best...The solution was simple. Thanks for everyone for helping me.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top