Lab 2
1 A note about this lab
This lab involves writing many static functions. Many of these could also be written as non-static methods. To reduce the cognitive load in the early part of this course, and to get a chance to practice with ‘switch‘ expressions, we will be sticking to static methods for this lab.
If you would like to define alternate non-static versions of these methods, you are welcome to; however, if you do, these should be done in addition to the static methods, rather than in place of them.
Also, you will have choices to make in how you want to represent things such as days and months; this is left up to you. You should be prepared to discuss your thought process.
Also: don’t use any of the built-in date libraries; they will just make your life more complicated, probably.
2 Getting Started
Follow the instructions from Lab 1 to create a new repository for lab 2.
3 Compound Data
3.1 Dates
Define a simplified date record, that contains a year, a month, and a day. Assume that leap years aren’t real, unless you are fond of complexity.
Write a non-test test case that simply creates three examples of these date records; these do not need to contain any uses of an assert statement.
For each of the following, follow the design recipe, and be sure to include a purpose statement, and to write test cases before implementing the methods.
Develop the static daysInMonth method that accepts a month, and returns the number of days in that month. Signal an error if the month is not valid.
Develop the static tomorrow method that accepts a date and returns the date representing the next day.
Develop the static dayOfYear method that returns the number of days since January first. More specifically, how many 24-hour periods have elapsed between noon on January first of the year and the noon on the given date?
Develop the static comesBefore method that accepts two dates and returns true if the first one comes before the second, or is the same as the second.
(skip and come back to this constructor part if your instructor hasn’t talked about it yet:)
Define a custom constructor that throws an "IllegalArgumentException" if the day or month is illegal, and then add ‘assertThrows‘ test to ensure that the check works correctly.
3.2 Date Ranges
Define a date-interval record, that contains two dates, start and end.
As before, use a "test case without tests" to provide at least three examples of date intervals.
Define a custom constructor that signals an error when the second date is prior to the first one.
Develop the static dateIntervalDays method that returns the number of days in the interval; that is, the number of 24-hour periods from noon on the "start" day to noon on the "end" day.
Develop the static dateOverlap method that accepts two dateIntervals and returns true if the intervals overlap. For the purposes of this question, regard an interval as starting at noon on the "start" day, and ending at 11:59 AM (a minute before noon) on the "end" day.
3.3 Nullable Date Ranges
For the next few functions (and the rest of your time programming in Java), it may often be useful to use ‘null‘, a special value that belongs to every type, to encode certain special conditions. For instance, you might represent "there is no answer", as in the two functions below, or "the list is empty", as is standard for linked lists.
In the following text, we will use the adjective "nullable" to refer to a type whose values should be possibly-null. Also, Linked Lists are always going to be nullable types. In other circumstances, for non-nullable inputs, your code does not need to check for null values. In case you’re interested, JEP draft 8303099 represents an attempt to bring this feature to Java.
Develop the static dateIntervalIntersect function, that takes two date intervals and returns a nullable date-interval representing their intersection.
Define a nullableDateIntervalIntersect function, that takes two nullable date-intervals and returns a nullable date-interval representing their intersection.
3.4 Date Lists
Develop a representation for linked lists of dates, using a nullable two-element record containing first and rest fields as we have done in class.
For all of the following methods, follow the list template, that uses a switch to act differently on empty and non-empty lists.
Develop the static listLen method, that returns the length of a list of dates.
Develop the static minDate method, that accepts a list of dates and returns a nullable date, specifically, the earliest date that occurs in it, or null if the list is empty.
Develop the static maxDate method, that accepts a list of dates and returns the latest date that occurs in it.
Develop the dateCover method, that accepts a list of dates and returns the shortest date interval that contains all of the dates. Hint: this method is pretty simple, use your existing functions.
Develop the allTomorrows method, that accepts a list of dates and returns a new list where each date is mapped to the following date. That is, if the fourth element of the first list is May 5th, the fourth date of the output list should be May 6th.
Develop the addToEnd method, that accepts a list of dates and a new date and returns the list with the new date at the end.
Develop the append method, that accepts two lists of dates and returns a new list containing all the elements of the first list followed by all the elements of the second list. Note that this is one of those rare cases where you do not want to use a an earlier method: it seems as though addToEnd might be useful, but this method is substantially easier and more efficient if you don’t use it.
3.5 Date Interval Lists
This section is optional. It might be good practice for an exam. It is not required.
Develop a representation for a linked list of date intervals.
Develop the static inOrder method that returns true when the start dates of the intervals in the list are increasing.
Develop the static condense method that accepts a list of date intervals that satisfies the ‘inOrder‘ method, and combines adjacend and overlapping intervals to produce a new date interval list that represents exactly the same set of dates, but contains no intervals that overlap or have one’s start date equal to another interval’s end date.