Personal tools
You are here: Home Classes Fall 2004 - Spring 2005 CS 150 labs lab5 Untitled Document
Document Actions

Untitled Document

by admin last modified 2005-05-11 13:31

Lab 5-- Making a calendar program

Overview

Here is the jar file for this lab. This week you will write a Calendar class. This completes a program that displays three types of calendars:

  1. If you give the program a date of the form m/d/y, as in 2/16/1952, it will respond with a text message telling the day of the week on which that date occurred: "February 16, 1952 is a Saturday."
  2. If you give the program a date of the form m/y, as in 12/1941, it will open a graphical window in which it draws a calendar for that month, which will look something like this:
    October 2003
    S
    M
    T
    W
    T
    F
    S
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31

  3. If you give the program only a year, as in 2003, the program will open up 12 windows in which it draws calendars for the 12 months of that year.

The program will work for any date after January 1, 1800.

The main() method for the program consists of a loop that prompts the user for dates then prints or draws the appropriate calendars for these dates. The loop terminates when you respond to the prompt with 0 rather than a date.

The algorithm

The same basic algorithm is behind all of these. In order to create a calendar, we need to be able to compute which day of the week a given date occurs on. Once we can do this, we can draw the calendar for a month by determining the start day of the month, then writing the numbers from 1 to the end of the month sequentially, staring a new row after printing each Saturday date.

The algorithm is based on the observation that every seventh day we get back to the same day of the week. For example, today is Thursday, October 2. Seven days from now, on October 9, it will again by a Thursday. Seven days after, on October 16, it will be Thursday again. In other words, we want to start with a known date and compute the number of days between that date and the date in question. When this total is divided by 7, it tells us the day of the week we want.

Let's look at a few examples. The year 2003 started on a Wednesday. There are 365 days between Jan. 1, 2003, and Jan. 1, 2004. The remainder of 365 divided by 7 is 1, so Jan. 1, 2004 must be a Thursday. The starting date for our program is going to be Jan. 1, 1800, which was a Wednesday. (This is convenient because there were several changes to the standard calendar in the preceding centuries, but there have been none since.) Now, suppose we want to know about March 3, 1802. The year 1800 had 365 days, 1801 also had 365 days. January, 1802 had 31 days, and February, 1802 had 28. Finally, there were 2 days in March of 1802 prior to March 3. Altogether this gives us 365+365+31+28+2 = 791 days between Jan 1, 1800 and March 3, 1802. Since 791%7 is 0, we see that March 3, 1802 must have been the same day of the week as Jan. 1, 1800, which we know was a Wednesday.

So here is the algorithm for finding the day of the week of date m/d/y: Add together 3 values: the number of days in all of the years from 1800 to y-1, then the number of days in all of the months of year y from month 1 to month m-1, then add d-1. Take this total % 7. If the result is 0, the date is a Wednesday, if 1 it is a Thursday, if 2 a Friday and so forth.

 

Contents of the jar file

If you unpack the jar file for lab 5 you will find several classes:

  • CalendarMain: This has the main input-compute-print loop for the program. You shouldn't need to change this at all.
  • MonthDisplay: This handles the graphical elements for window with a month's calendar.
  • SimpleInput: This is Michael Barnes's class for text input. It is only used in CalendarMain.
  • WindowCloser. This is another class from the text (p. 600 if you are interested). It allows the program to close some or all of the month calendar windows without closing down the whole program.
  • Calendar: This is the only class you need to modify. It has all the computational elements of the program.

The structure of the Calendar class

The only class you need to work with is the Calendar class. This has variables month, day, and year; one Calendar object represents a single date. There are three constructors: one that takes month, day and year values, one that takes only month and year values (and sets the day to 1, the first day of the given month), and a default constructor with no arguments that sets the date to Jan. 1, 1800. There are only a few public methods: a set()method and a read() method that change the date associated with a Calendar object, and accessors getMonth(), getDay(), and getYear(). There are all written and you should not need to change them. There are also three public methods that you need to implement in this lab: printDate(), which prints the day of the week corresponding to the object's date, printMonth(), which draws a graphical calendar for the object's month, and printYear(), which draws 12 graphical calendars for the twelve months of the given year.

Calendar also has a number of private methods that help with the code for the public methods. Two of these just return strings: monthString(int m) takes a month (between 1 and 12) and returns the name of the month: "January", "February", etc. Method dayString(int d) is similar: it takes a day (between 0 and 6) and returns "Sunday", "Monday", etc. Note that Sunday is coded 0 and January is coded 1; you need this information for the methods you will write. There is also an isLeapYear(int y) method that returns a boolean value; you probably wrote such a method in lab4. All of these private methods are already written. The following are left to you to write:

  • int daysInYear(int y): returns the number of days in year y (either 365 or 366)
  • int daysInMonth(int m, int y): returns the number of days in month m of year y. The year only matters in
    the case of February, month 2.
  • int countDays(int m, int d, int y): This counts the number of days starting with January 1, 1800 and up to,
    but not including day (m, d, y).
  • int dayOfWeek(int m, int d, int y): This returns 0 if the given date falls on a Sunday, 1 if it falls on a Monday, etc.

You then need to write the 3 major public methods:

  • void printDate();
  • void printMonth();
  • void printYear()

 

Part 1: Days of the week

 

It should be easy to uses the isLeapYear() method to help you write daysInYear(int y), which returns the number of days in year y (either 366 or 365, depending on whether y is a leap year) and daysInMonth(int m, int y), which returns the number of days in month m of year y (the year is only relevant for February, month 2). Finally, you need to write countDays(int m, int d, int y). This returns the number of days between 1/1/1800 and m/d/y. You get this by summing the number of days in each year from 1800 to y-1 (a for-loop is handy here), the number of days in each month of year y prior to month m (another loop) and d-1. Why d-1? This is because we start counting at 1; the number of days between Jan. 1, 1800 and Jan. 2, 1800 is 1, not 2.

For method dayOfWeek(int m, int d, int y) think of the total returned by countDays() and the remainder we get when this is divided by 7. The remainder tells us the day of the week: 0 indicates Wednesday (remember that Jan. 1, 1800 was a Wednesday), 1 indicates Thursday, and so forth. Now, this doesn't fit nicely with our other methods -- dayString() thinks 0 indicates Sunday. Accordingly, method dayOfWeek() translates the remainder it computes into values the other parts of the program expect. If the remainder is 0, it returns 3 (to indicate Wednesday); if the remainder is 1 it returns 4 (for Thursday), and so forth. There are several ways to do this translation. One is to have a big if-then-else statement that looks at each possible value of the remainder and returns the correct number in response. There are more elegant ways to do this if you like. Make a list of the days of the week, the value of the remainder in each case, and the value you want to return. You should be able to see a mathematical way to change the remainder into the correct value.

The printDate() method that prints a string telling the day of the week corresponding to the date stored in the current Calendar object is already written for you. At this point the program should correctly calculate days of the week for given dates. Test it out with some dates you know and make sure this is correct before you proceed with Part 2.

Part 2: Month calendars

October 2003
S
M
T
W
T
F
S
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

Method printMonth() draws the calendar for the month stored in the current Calendar object. This makes use of the MonthDisplay class. printMonth already calls the constructor for MonthDisplay, which results in a window with the name of the month at the top. The MonthDisplay object returned by the constructor is stored in a variable called display. MonthDisplay has one public method: setDate(int row, int column, int number). Here "column" has values between 0 and 6, for the 7 days of the week. "row" has values betwen 0 and 5, because a calendar for 31 days that starts on Saturday might take up parts of 6 different rows. "number" is the date you want to print in the given row and column of the calendar; this should be a value between 1 and 31.

Now, you want to have a loop that walks through the dates from 1 to the number of days in the month. For each date you must decide the row and column where it belongs. The first day of the month always belongs in row 0; its column should be the value returned by dayOfWeek for day 1 of the given month and year. After this, with each step you increase the column by 1. After you put something in column 6, increase the row by 1 and set the column to 0. At the end of this loop you will have your calendar.

Part 3: Year calendars

After everything else, this part is easy, like a light desert after a big meal. You know how to print a month calendar; you print a year calendar by printing month calendars for the 12 months of the year. A loop lets you run through the months from 1 to 12. Since the month calendar uses the month and year stored in the Calendar object, you will need to make an appropriate object for each month. You might construct one Calendar object before entering the loop, then with each iteration using the set method for Calendar to change its month, day, and year to appropriate values.

 

 

 

Powered by Plone CMS, the Open Source Content Management System

This site conforms to the following standards: