gregorian calendar

Posted on 2003-02-22
Medium Priority
Last Modified: 2010-04-01
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.
Question by:cota50
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
LVL 11

Accepted Solution

cup earned 200 total points
ID: 8002098
Have a look at http://www.codeguru.com/date_time/DayOfWeek.html.  Also look at the comments, especially for dates before 1582.  You could always use Zeller's congruence in http://www.codeguru.com/mfc/comments/40976.shtml which is a lot simpler.

Reversing Zeller's congruence is a bit iterative.  What you could do is convert the date to a number then bung int into the reverse function then check if it is the dates you put in.  If it is then the date is valid.  If it isn't then it is a bad one.

29Feb2000 = 29Feb2000
29Feb2001 = 01Mar2001

So the 2nd date is invalid.

Expert Comment

ID: 8002206
check out


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. )
LVL 12

Expert Comment

ID: 8002813
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.

LVL 11

Expert Comment

ID: 9784220
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.


-bcl (bcladd)
EE Cleanup Volunteer

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

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

When writing generic code, using template meta-programming techniques, it is sometimes useful to know if a type is convertible to another type. A good example of when this might be is if you are writing diagnostic instrumentation for code to generat…
Unlike C#, C++ doesn't have native support for sealing classes (so they cannot be sub-classed). At the cost of a virtual base class pointer it is possible to implement a pseudo sealing mechanism The trick is to virtually inherit from a base class…
The goal of the video will be to teach the user the concept of local variables and scope. An example of a locally defined variable will be given as well as an explanation of what scope is in C++. The local variable and concept of scope will be relat…
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.
Suggested Courses

777 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question