Link to home
Start Free TrialLog in
Avatar of cota50
cota50

asked on

gregorian calendar

I am trying to write a program to input a month, day, year, and return the day of the week. The program should weed out invalid dates input. I am having trouble returning the specific day of the week.
any help is much apreciated. Thanks.
ASKER CERTIFIED SOLUTION
Avatar of cup
cup

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of burcarpat
burcarpat

check out

    http://www.boost.org/libs/date_time/doc/index.html

for a peer-reviewed date-time library, supported by many c++ standards committee members via boost.org.  the lib is cross-platform and works with many platforms and compilers w/o any problems and it's 100% free ( i.e. free for commercial use, etc. )
If this isn't homework you can probably use boost library as burcarpat suggest.

If it is homework you probably can't but in this case we can't really help you too much either. I will provide a few hints though.

Input year, month, date.

I will assume they are integers such that year == 2003 indicate the current year, month == 2 for february and date == 20 for the 20th day of the month.

So February 23rd, 2003 would be year == 2003, month == 2, day == 23.

Now, you can first examine year, you probably have a range of valid years. You should certianly be wary of negative years or the year 0. Also, for gregorian calendar, you probably shouldn't allow years prior to 1582 or whatever time it was that pope Gregor decreed the calendar to be used. In england and its colonies the calendar wasn't in use until sept 4th 1752 and so you might even not allow any date before then.

Next you can validate the month, the month is easy enough, it should be a number in the range 1..12 both inclusive.

Lastly you can validate the day of the month. For all months except february the number of days in a month is fixed and so can be cchecked against a table.

Define a table like this: (remember that C++ is 0 based for arrays).
//                       jan feb mar apr may jun jul aug
const int mdays[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31,
//    sep oct nov dec
      30, 31, 30, 31 };

if (day < 1 || day > mdays[month])
   day is invalid.

One exception is february where the number of days in the month is 29 for leap years and 28 for other years.

if (month == febraury && is_leap(year))
   mdays[february] = 29;

can be done prior to testing for the day.

One problem is that mdays[] is constant and cannot be modified, but there are lots of ways to get around that. Either remove the const but an even better solution is to keep it as const but program around it.

if (month != february || ! is_leap(year)) {
   // general test.
   days_in_current_month = mdays[month];
} else {
   days_in_current_month = 29;
}
if (day < 1 || day > days_in_current_month) {
   // invalid
} else {
   // date is ok.
}

Now that you have verified the data you can move on to find the weekday.

First find how many days since the day before january 1st, year 1.

As I said, the gregorian calendar wasn't in use at such a year so nobody at that time would know that today was january 1st. However, it is very possible to count backwards as if the calendar was in use and then we reach a specific day which can be called "january 1st, year 1".

How many days since that day?

Well, this question can be divided into two questions:

Q1: How many days between January 1st in the given year and that day?

Q2: How many days between the given date and january 1st in the same year?

The first question depends only upon the year and not on the month or day. There are 365 days in all regular years and 366 days in all leap years. The leap year rule for gregorian calendar is as follows:

1. If a year is not divisible by 4 it is not a leap year.
2. If a year is divisible by 4 but not by 100 it is a leap year.
3. If a year is divisible by 100 but not by 400 it is not a leap year.
4. If a year is divisible by 400 it is a leap year.

It turns out that gregorian calendar follow a 400 year cycle which has first a 100 year period with leap year every 4th year and then 3 100 year periods with leap year every 4th year except the first. In 400 year we have leap year every 4th year except 3 times. so we have 97 leap years in that 400 year period.

If we first subtract 1 from year we get how many years it is up to and including the previous year:

pyear * 365 + pyear / 4

would count the number of days if we had leap year every 4th year, but we must also count the 100 and 400 year rules:

tot_days = pyear * 365 + pyear / 4 - pyear / 100 + pyear / 400;

This answers Q1.

Q2 is simply the number of days into the current year that the date specifies. This question can again be divided into two questions:

Q2a) How many days between january 1st and the last day of previous month.

Q2b) how many days between the last of the previous month and the given date?

Q2a is simply the sum of 31 + 28(or 29) + 31 + 30... etc up to but not including the current month.

Use 28 for regular years and 29 for leap years for february, otherwise the numbers are taken from the mdays[] table.

Q2b is simply the value of 'day'.

Thus you can count how many days between a year,month,day and janauary 1st, year 1.

Now, actually we counted one day extra so that january 1st, year 1 would get a count of '1' and so on and that day happen to be a monday so if we take this total and divide by 7 we get how many weeks has passed and more importantly, the remainder of that division tells us how many weekdays that has shifted between the two dates.

so weekday = total_days % 7; will get a value such that 0 means sunday, 1 means monday, and so on until 6 which means saturday.

This answers the problem.

Go and write your program.

Alf
No comment has been added lately, so it's time to clean up this TA.
I will leave a recommendation in the Cleanup topic area that this question is:

Answered: Points to cup

Please leave any comments here within the next seven days. Experts: Silence
means you don't care.

PLEASE DO NOT ACCEPT THIS COMMENT AS AN ANSWER!

-bcl (bcladd)
EE Cleanup Volunteer