Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
Solved

# C++ Calendar Day Counter

Posted on 2003-02-19
Medium Priority
1,252 Views
I'm doing a program for my C++ class and the program has me stumped. I'm just starting programming and don't know too much.
Here is what our program must do.
1. has to start from Sept 4, 1752 (when Gregorian calendar started(
2. have to enter in the int month, int day, int year
3. has to print out the day of the year it is. (like it is day 61 of the year).
4. It has to display which day it is as well.

Any help on starting this program would be great. I'm just lost on it.

Kris
0
• 2
• 2
• 2

LVL 12

Accepted Solution

Salte earned 300 total points
ID: 7986151
Oh, calendars are fun!!!!

If you get int day, int month and int year values then here is how to calculate certain interesting numbers.

How many days into the year is it?

For this question we can almost forget about the year and only care about month and day. We cannot forget the year completely because the count differ from leap years and other years but we take that after. For now, forget the year and concentrate on the month:

If the month is january then 0 days has passed before this month into the year.

If the month is february then january has passed. January is 31 days so 31 days has passed.

So we get a table something like:
//                    jan feb mar apr may jun jul aug
const int mdays[] = { 31, 28, 31, 30, 31, 30, 31, 31,
30, 31, 30, 31 };

A few notes about this table, this table list how many days in each month, so to get the number of days that has passed when you are in month M you need to add all the numbers before the month M. Also if you get the month with january as 1 you must remember that C++ has lowest index equal to 0 so you should subtract one. January shouldn't add any numbers and get a sum of 0. February should only count the lowest index (0) and stop before 1 and get a sum of 31. March should stop at index 2 and get the sum 59 etc.

If you want you can just make the table have the sums instead, if so the table will be:

//  first index not used     jan feb mar apr may jun  jul
const int mdays_sum[] = { 0, 0, 31, 59, 90, 120, 151, 181,
//  aug  sep  oct  nov  dec  full year
212, 243, 273, 304, 334, 365 };

This table also have 0 at index 0 so you can just put the month directly as index to the table.

Now that we know how many days before this month then we can find how many days into the year:

year_day = mdays_sum[month] + day;

Now, this is correct if the year is not a leap year and it is correct if the month is < march.

If leap year and month >= march this hasn't counted the leap year day of february 29 so we add 1:

++year_day;

under that condition.

Which year is leap years? If you count gregorian calendar the rule is as follows:

1. If the year is not divisible by 4 the year is not a leap year.

2. If the year is divisible by 4 but not by 100 the year is a leap year.

3. If the year is divisble by 100 but not by 400 the year is not a leap year.

4. If the year is divisible by 400 it is a leap year.

Sound complicated? Actually it isn't so bad, Every year divisible by 4 is a leap year except that in a period of 400 years 3 of those years aren't leap years even if they are divisible by 4. This give a count of 146097 days in a period of 400 years. (this is actually easy to calculate in your head, 4 years is 1461 days (4 * 365 + 1) so 400 years would be 146100. Since that is 3 leap days too much the real count is 146097 = (4 * 365 + 1) * 100 - 3.

bool is_leap(int year)
{
return (year & 3) == 0 &&
((year % 100) != 0 || (year % 400) == 0));
}

I used (year & 3) as a 'fast mod 4' operation.

so if (is_leap(year)) ++year_day;

will correctly calculate the year_day.

How to display the day? As in YYYY-MM-DD or M/D/YYYY or D.M.YYYY or some such format? That should be easy enough you already have the int values for each, just print them out.

If you mean the count of days since gregorian calendar started you probably need to do some more work.

If you want to calcualte the weekday it is easy enough:

Perhaps you want the weekday to be a number so that 0 = sunday, 1 = monday, ...6 = saturday? If so do this way.

step 1. Count the number of days since a fixed day. That day must have a known weekday. Also the day should be at some time in the past, it doesn't have to really exist. I.e. it can be a date before the sept 4th or 1752 and probably should be, that way all your day counts are positive.

step 2. Add the day number in the year to the count from step 1.

step 3. since this count number of days since that fixed day, just do daycount % 7 and you get the weekday number, if the result is 0 the day with the daycount is the same weekday as the fixed day, if 1 it is the next etc.

So the real problem here is to count that daycount. This is easy enough. we use a fixed day of the fictuous day of January 1st year 1 BC.

Also, remember we count the number of days up to january 1st of the given year so the number of years in that period is year - 1.

So the day count is:
pyear = year - 1; // previous years

daycount = pyear * 365 + (pyear / 4) - (pyear / 100) + (pyear / 400);

Now the formulae is simply (daycount % 7) but that will give us a day starting with the weekday of that day, what weekday is that?

It turns out that it is a sunday:

To verify let me check current date:

year = 2003, pyear = 2002

daycount = 2002 * 365 + (2002/4) - (2002/100) + (2002/400);

Note that all the divisions are integer divisions and will only work if the pyear value is >= 0.

daycount = 730730 + 500 - 20 + 5 = 731215

We are in month february so year day count is 31 + 20 = 51

so the total daycount is 731215 + 51 = 731266

731266 % 7 = 4 = thursday

For calculations in your head there is a simpler method, but that method is harder to use in a computer program.

Here is how to find the weekday of any day using simple arithmetic (+ and - and possibly one division by 12).

I will introduce the method by starting with simple dates and then gradually work myself around to any year and date.

Let's start simple: What weekday is April 4th 1600?

Easy enough, this one single day is worth memorizing, just remember that it was a tuesday.

Ok, so what weekday is April 4th 2000?

Easy enough, the calendar repeats itself every 400 years (the 146097 days of a 400 year period is exactly 20871 weeks - no days left over). This means that knowing that single day you also know that april 4th 2400 will fall on a tuesday etc if we still keep the gregorian calendar at that time that is.

Ok, but what about April 4th 1700 or April 4th 1800 or April 4th 1900?

Easy enough, starting from april 4th 1600 there are exactly 24 leap years to april 4th 1700 so the change of weekday is 2 days behind. April 4th in those years are in other words:

1600 - tuesday
1700 - sunday
1800 - friday
1900 - wednesday

Note that between 1900 and 2000 there's an extra leap day on February 29th 2000 so April 4th 2000 does not fall on monday but on tuesday so the 400 year cycle is repeated.

Ok, so now we know april 4th of any century. What about years within a century?

April 4th 1956?

Easy enough, there are two ways you can do this. One is kinda tricky and require you to add groups of 12 or 28 years at a time while the other is more straightforward but require a division of 12. However, the number you divide is always in the range 0-99 so the division isn't that complicated.

The 12 or 28 comes from the following observations:

1. Within a 100 year period the extra leap year rules does not come into play so a simple "every 4 year leaps" is the only rule to use.

2. Every 12 years the calendar is shifted by 1 day so if April 4 is on monday one year then 12 years later it will be on a tuesday etc. Since we count in units of 12 years the 4 year leapday cycle doesn't create any disturbance, if the original year was 2 years into a leap year cycle then 12 years later that year is also exactly 2 years into a leap year cycle.

3. Since every 4 year is a leap year and we have 7 days a week then every 28 years the calendar must repeat, so 1929 has exactly the same calendar as 1901 and 1928 after february has exactly the same calendar as 1900 after february. January and february aren't the same since 1900 is not a leap year while 1928 is.

The division is then very simple and straight forward:

if a year is ccyy mm dd

then yy is the century part of the year and we divide it by 12. This gives us a quotient and a remainder r.

Then you simply add 1 for the quotient and 1 for the remainder and 1 for for every complete 4 year cycle of the remainder. Or:

q = yy/12, r = yy % 12

x = q + r + (r / 4);

r is a number in the range 0-11 so r/4 is 0 for r in 0-3, 1 for r in 4-7 and 2 for r in 8-11.

Since we only care about weekdays we can also remove any multiples of 7 in that calcualtion:

x = x % 7

what we end up with is a number 0 indicating that april 4 of that year is the same as april 4 of the year cc00 a value of 1 means it is the day following the weekday of april 4 cc00 etc.

Example: April 4 1952

52 = 4 * 12 + 4
April 4 1900 was wednesday so is a value of 3.

1900   52/12   52%12     ((52%12)/4)
3    + 4     + 4      +   (4/4) = 3 + 4 + 4 + 1 = 12
since we remove 7s we get 12 - 7 = 5.

April 4 1952 was a friday.

Now, what is this about april 4? I want to find some other day, like june 8th or something?

Well, for any year april 4 or 4/4 is the same weekday as 6/6 8/8 10/10 and 12/12. Just check your calendar!

So june 6th has the same weekday as april 4th so june 6 1952 is therefore a friday and so june 8th must be a sunday.

Well, remember this: "I work from 9 to 5 on 7-11"

And then recognize that 9/5 5/9 7/11 and 11/7 also fall on the same day as 4/4 6/6 8/8 10/10 and 12/12.

This covers april, may, june, july, august, september, october, november and december.

What about march? Well, the fictuous date of march 0th also fall on the same day. This means that march 7 does as well etc. But remembering march 0th also gives you a link to february, because march 0th is none other than february 28th on regular years and february 29th on leap years.

So for regular years it is also the same weekday as february 0th or january 31st or january 3rd.

For leap years it is the same weekday as february 1st and january 4th.

There you have the full calendar.

A final example: September 11th 2001 (that infamous day).

2000 april 4th is the same as 1600 - tuesday.
2001 april 4th is therefore a wednesday.
Thus 9/5 is also a wednesday and so 9/11 being 6 days later is a tusday.

Good luck with your calendar fun!

Alf
0

Author Comment

ID: 7989006
thanks for alot of help Alf.
Blown away :)
Just a few more questions.
how do i get the output to look like this:

That is day number 61 of the year.
It is a Wednesday.

How would i rig the program like that.
Kris
0

Author Comment

ID: 7989020
thanks for alot of help Alf.
Blown away :)
Just a few more questions.
how do i get the output to look like this:

That is day number 61 of the year.
It is a Wednesday.

How would i rig the program like that.
Kris
0

LVL 12

Expert Comment

ID: 7996001
well, the output of prompt text "Please input the month: " is done by a simple:

cout << "Please input the month: ";

cin >> month;

would then read the month. Remember that cin now has a '\n' and possibly some other whitespace before the newline also that you must get rid of before you read more, so:

cin.ignore(1024,'\n');

will remove that.

Thus you can read in month, day and year.

Then you do the calculations and you get something like 61 and 3 for weekday. The number 61 is simply output by:

cout << "That is day number " << daynum << " of the year." << endl;

The weekday is best placed in a small array:

const char * weekdays[] = {
"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
"Friday", "Saturday" };

cout << "it is a " << weekdays[wday] << endl;

Would then output the weekday name as well.

Alf
0

LVL 2

Expert Comment

ID: 8867114
This question has been abandoned. I will make a recommendation to the moderators on its resolution in a week or two. I appreciate any comments that would help me to make a recommendation.

In the absence of responses, I may recommend DELETE unless it is clear to me that it has value as a PAQ. Silence = you don't care

Udil
EE Cleanup Volunteer
0

LVL 2

Expert Comment

ID: 8951118
This question didn't show any activity for more than 21 days. I will ask Community Support to close it unless you finalize it yourself within 7 days.
Unless there is objection or further activity,  I will suggest to

Udil
EE Cleanup Volunteer
0

## Featured Post

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Written by John Humphreys C++ Threading and the POSIX Library This article will cover the basic information that you need to know in order to make use of the POSIX threading library available for C and C++ on UNIX and most Linux systems.   [sâ€¦
Introduction This article is the first in a series of articles about the C/C++ Visual Studio Express debugger.  It provides a quick start guide in using the debugger. Part 2 focuses on additional topics in breakpoints.  Lastly, Part 3 focuses on thâ€¦
The viewer will learn how to use the return statement in functions in C++. The video will also teach the user how to pass data to a function and have the function return data back for further processing.
The viewer will learn how to user default arguments when defining functions. This method of defining functions will be contrasted with the non-default-argument of defining functions.
###### Suggested Courses
Course of the Month14 days, 5 hours left to enroll