CMPS 134 Fall 2022
Prog. Assg. #6: The CalendarDate Instance Class
Due Date: 11:59pm, November 22. (Deadline 48 hours later)

For this assignment, you are to complete the Java instance class CalendarDate, which, as given, has several "stubbed" methods for you to complete. As its name suggests, each instance of the class represents a calendar date, such as March 25, 1987 or December 3, 2021.

Two of the stubbed methods —equals() and compareTo()— are for the purpose of comparing two calendar dates. The remaining stubbed methods are mutators whose purpose is to either "advance" a calendar date forward in time or to have it "retreat" backward in time. The units of time by which a date can be changed are a day, a week, a month, a year, or a multiple of any of those.

The meaning of advancing/retreating by a day or by a week is clear. Less clear is what is meant by advancing/retreating by a month, due to different months having different numbers of days. Advancing/retreating by a year is also ambiguous, due to the existence of leap years.

Here are the rules that we shall adopt, which seem to be consistent with answers that Google provides in response to questions such as "What is the date one month before February 29 2020?":

These rules give rise to some results that may be counterintuitive. For example, advancing one month from March 31 (which has 31 days) puts you at May 1, completely bypassing April (which has only 30). Meanwhile, retreating one month from March 31 (in a non-leap year) puts you at March 3, because February has only 28 days.

Among the private methods in CalendarDate, three that you should find useful are yearDays(), monthDays(), and isLeapYear(). Don't duplicate their logic in other places!


Testing

To aid you in testing your work, the Java application CalendarDateTester is provided. Below is a sample user/program dialog. (The commands are case-insensitive, which is to say that it doesn't matter whether you use upper or lower case letters.) A number of the interactions demonstrate results that you may find counterintuitive but that are consistent with the rules for advancing/retreating by months/years.

Welcome to the CalendarDateTester program.

Enter date in mm/dd/yyyy format: 11/14/2022

:> h
Available commands ([n] means optional natural number):
-------------------------------------------------------
  Q        (Quit)
  H        (Help)
  E        (test Equals())
  C        (test compareTo())
  S date   (test setDate(date))
  RD [n]   (test retreatDay())
  AD [n]   (test advanceDay())
  RW [n]   (test retreatWeek())
  AW [n]   (test advanceWeek())
  RM [n]   (test retreatMonth())
  AM [n]   (test advanceMonth())
  RY [n]   (test retreatYear())
  AY [n]   (test advanceYear())

:> ad
After calling advanceDay(), current is 11/15/2022 and prev is 11/14/2022

:> ad 45
After calling advanceDay(45), current is 12/30/2022 and prev is 11/15/2022

:> am
After calling advanceMonth(), current is 01/30/2023 and prev is 12/30/2022

:> rm
After calling retreatMonth(), current is 12/30/2022 and prev is 01/30/2023

:> ay 23
After calling advanceYear(23), current is 12/30/2045 and prev is 12/30/2022

:> e
equals() says that 12/30/2045 and 12/30/2022 are NOT equal.

:> c
compareTo() says that 12/30/2045 comes after 12/30/2022

:> S 03/31/2022
After calling setDate(03/31/2022), current is 03/31/2022 and prev is 12/30/2045

:> AM
After calling advanceMonth(), current is 05/01/2022 and prev is 03/31/2022

:> S 05/01/2022
After calling setDate(05/01/2022), current is 05/01/2022 and prev is 05/01/2022

:> e
equals() says that 05/01/2022 and 05/01/2022 are equal.

:> RM
After calling retreatMonth(), current is 04/01/2022 and prev is 05/01/2022

:> S 01/31/2020
After calling setDate(01/31/2020), current is 01/31/2020 and prev is 04/01/2022

:> AM
After calling advanceMonth(), current is 03/02/2020 and prev is 01/31/2020

:> S 03/02/2020
After calling setDate(03/02/2020), current is 03/02/2020 and prev is 03/02/2020

:> RM
After calling retreatMonth(), current is 02/02/2020 and prev is 03/02/2020

:> S 02/29/2020
After calling setDate(02/29/2020), current is 02/29/2020 and prev is 02/02/2020

:> AM
After calling advanceMonth(), current is 03/29/2020 and prev is 02/29/2020

:> S 02/29/2020
After calling setDate(02/29/2020), current is 02/29/2020 and prev is 03/29/2020

:> RM
After calling retreatMonth(), current is 01/29/2020 and prev is 02/29/2020

:> S 02/29/2020
After calling setDate(02/29/2020), current is 02/29/2020 and prev is 01/29/2020

:> AY
After calling advanceYear(), current is 03/01/2021 and prev is 02/29/2020

:> S 02/29/2020
After calling setDate(02/29/2020), current is 02/29/2020 and prev is 03/01/2021

:> RY
After calling retreatYear(), current is 03/01/2019 and prev is 02/29/2020

:> S 12/25/2022
 After calling setDate(12/25/2022), current is 12/25/2022 and prev is 03/01/2019

:> Q
Goodbye.

The program maintains two CalendarDate objects, one referred to as current and the other as prev (for "previous"). Each time a command to advance or retreat is entered, prev takes on the value of current and then the relevant mutator method is applied to current. Afterwards, their values are displayed.

When entering a command to make current advance or retreat, you can either include a natural number or not. The number (which is expected to be nonnegative) indicates by how many of the specified time units you want current to advance or retreat (e.g., 23 days). Omitting a number means, in effect, one. However, note that, for example, the commands "AD 1" and "AD" (the latter lacking any number) are not the same, in the sense that the former triggers a call to the one-argument version of advanceDay() whereas the latter triggers a call to the zero-argument version of that method.

The E and C commands are for comparing current and prev using, respectively, equals() and compareTo().


Testing using a GUI

As an alternative (or in addition) to using CalDateTester for testing your work, you could make use of the CalendarDateGUI application, which presents the user with a graphical user interface! In support of it, you will also need the Java classes CommandButtons and DialogBox.

CalendarDateGUI makes use of advanced features that we have not (and will not) study in this course, and it is quite unlike any of the other programs we have used this semester (other than jGrasp!) in that it presents the user with a graphical user interface employing tables, buttons, and dialog boxes. As such, it is designed to operate in an "event driven manner" rather than in the "command driven manner" of all our previous programs. It is hoped that you will find this kind of interface to be familiar and intuitive. However, even a brief inspection of the source code will make it clear that the design and instructions required to provide for this type of interaction are far more involved than anything we have seen so far in this course.


Program Submission

You are to submit one file, CalendarDate.java, in the familiar manner. (Of course, you may submit that file multiple times, as you make corrections or other improvements.) Remember to complete the "header comments" that ask you to identify yourself, anyone who collaborated with you, and any defects of which you are aware.