CMPS 144L Fall 2023
Lab #2 (Sept. 7): TimeOfDay

The Java class TimeOfDay is incomplete, and your task is to bring it as close to completion as you can. To aid you in that, the Java application TimeOfDayTester is provided. Its purpose, as its name suggests, is to test the various features of TimeOfDay. (You are free to modify it in any way you see fit.) Another tool that can be used for testing is jGrasp's Workbench utility, as has been illustrated in lecture.

A sample dialog between a user and TimeOfDayTester appears near the end of this document.

It is highly recommended that you take several minutes to study the source code of TimeOfDay in order to come to an understanding of how its features are implemented.

Once you have done that, you will be in a position to fill in the missing bodies of several "stubbed" methods, as described next. Your tasks are listed below, in order from easiest to hardest (at least in your instructor's opinion). But you may work on them in any order you wish. Use TimeOfDayTester each time (you think) you have completed a method in order to test it.

  1. Complete the isLaterThan() method. (Examine the isEarlierThan() method for ideas.)
  2. Complete the twoDigitImageOf() method, upon which the toString() method relies to produce numerals with a leading zero, as in the minute component of "5:08AM".
  3. Complete the goBackwardByOneMinute() method. It is the inverse of the given goForwardByOneMinute() method, in that calling one of them, followed by calling the other, should have no net effect upon the "target" TimeOfDay object.
    Note: The object to which a method is applied is sometimes called the "target" object. (Other people call it the "implicit parameter".) For example, an object referred to by time is the target object with respect to the method call time.goForwardOneMinute(). End of note.
  4. Complete the goForwardByMinutes() method. One approach —one might call it the naive approach— is to make repeated calls to the goForwardByOneMinute() method.

    A superior approach would be to make use of the division (/) and remainder (%) operators. As an example, suppose that the parameter passed to the method were 4445. There are 1440 minutes during each day (which one can compute by multiplying HOURS_PER_DAY by MINUTES_PER_HOUR, the two symbolic constants defined in the TimeOfDay class). Because 4445 / 1440 is 3 and 4445 % 1440 is 125, going forward by 4445 minutes means going forward by three days and 125 minutes. But a clock does not distinguish one day from another, and so this is equivalent to going forward by 125 minutes. (Indeed, the quotient 4445 / 1440 is irrelevant; only the remainder is significant.)

    At this point, we can compute 125 / MINUTES_PER_HUUR to obtain the number by which the instance variable hour should increase (wrapping around to zero if appropriate) and 125 % MINUTES_PER_HOUR to obtain the number by which the instance variable minute should increase (wrapping around to zero if appropriate and, in that case, necessitating that hour be increased by one more).

  5. Complete the setTo24HourMode() and setTo12HourMode() methods. The intent here is that a TimeOfDay object should be in one of two possible modes —12-hour or 24-hour— according to which of those two methods was invoked upon it most recently. (Let's agree that a new TimeOfDay object should be in 12-hour mode.)

    When a TimeOfDay object is in 12-hour mode, its toString() method should produce a string describing the time in the traditional (i.e., AM/PM) format, as in "8:45AM" or "12:06PM". But if such an object is in 24-hour mode, its toString() method should produce a string in the form hh:mm, as in "09:37" or "19:02". Indeed, the only effect that an object's mode should have is to determine the format of the string produced by toString(). The mode should have no effect upon how the values of instance variables hour and minute are used/interpreted for representing the time of day.

    To implement this feature, it is necessary not only to modify the toString() method (which, as given, produces strings in the traditional AM/PM format), but also to provide a means by which a TimeOfDay object is able to "remember" which mode it is in. (Question: How does an object remember something about itself?)

  6. Complete the goBackwardByMinutes() method. Analogous to goForwardByMinutes(), a naive approach is to repeatedly call goBackwardByOneMinute().

    A more clever approach translates a backward movement into an equivalent forward movement and then calls goForwardByMinutes(). For example, going backward by 120 minutes (two hours) has the same effect as going forward by 1320 minutes (22 hours) (which we get using 1440 - 120).

    Of course, you must also take into account that the movement might be by more than 1440 minutes (i.e. a whole day). Thus, first take the remainder when 1440 is divided into that number. For example, if the movement backwards is 4000 minutes, that is the same as moving 4000 % 1440 (which is 1120) minutes backwards. Which is the same as going forward by 1440 - 1120, or 320, minutes.


Example Dialog with TimeOfDayTester

The program maintains two TimeOfDay objects, one referred to as current and the other as prev (for "previous"). Each time a command that calls for a mutator method to be called, prev takes on the value of current and then the relevant mutator method is applied to current. Afterwards, the value of each of them (i.e., the string produced by toString()) is displayed.

Welcome to the TimeOfDayTester program.

Enter initial hour and minute values: 15 57

After initialization, current is 3:57PM and prev is 12:00AM

Available commands (h, r, and n stand for natural numbers):
-----------------------------------------------------------
  Q        (Quit)
  H        (Help)
  C        (test compareTo(prev))
  E        (test isEarlierThan(prev))
  L        (test isLaterThan(prev))
  S h r    (test setTo(h,r))
  GF       (test goForwardByOneMinute())
  GF n     (test goForwardByMinutes(n))
  GB       (test goBackwardByOneMinute())
  GB n     (test goBackwardByMinutes(n))
  12       (test setTo12HourMode())
  24       (test setTo24HourMode())

> GF
After calling goForwardByOneMinute(), current is 3:58PM and prev is 3:57PM

> GF 37
After calling goForwardByMinutes(37), current is 4:35PM and prev is 3:58PM

> C
compareTo() says that 4:35PM is greater than 3:58PM

> GB
After calling goBackwardByOneMinute(), current is 4:34PM and prev is 4:35PM

> GB 52
After calling goBackwardByMinutes(52), current is 3:42PM and prev is 4:34PM

> E
isEarlierThan() says that 3:42PM is earlier than 4:34PM

> L
isLaterThan() says that 3:42PM is NOT later than 4:34PM

> S 5 8
After calling setTo(5,8), current is 5:08AM and prev is 3:42PM

> 24
After calling setTo24HourMode(), current is 05:08 and prev is 3:42PM

> 12
After calling setTo12HourMode(), current is 5:08AM and prev is 3:42PM

> Q
Goodbye.


Submitting Your Work

Submit your TimeOfDay.java source code file to the Brightspace dropbox for Lab #2.