1.
1 package ADT; 2 3 import algorithms.util.StdOut; 4 5 /****************************************************************************** 6 * Compilation: javac Date.java 7 * Execution: java Date 8 * Dependencies: StdOut.java 9 * 10 * An immutable data type for dates. 11 * 12 ******************************************************************************/ 13 14 /** 15 * The <tt>Date</tt> class is an immutable data type to encapsulate a 16 * date (day, month, and year). 17 * <p> 18 * For additional documentation, 19 * see <a href="http://algs4.cs.princeton.edu/12oop">Section 1.2</a> of 20 * <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne. 21 * 22 * @author Robert Sedgewick 23 * @author Kevin Wayne 24 */ 25 public class Date implements Comparable<Date> { 26 private static final int[] DAYS = { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; 27 28 private final int month; // month (between 1 and 12) 29 private final int day; // day (between 1 and DAYS[month] 30 private final int year; // year 31 32 /** 33 * Initializes a new date from the month, day, and year. 34 * @param month the month (between 1 and 12) 35 * @param day the day (between 1 and 28-31, depending on the month) 36 * @param year the year 37 * @throws IllegalArgumentException if this date is invalid 38 */ 39 public Date(int month, int day, int year) { 40 if (!isValid(month, day, year)) throw new IllegalArgumentException("Invalid date"); 41 this.month = month; 42 this.day = day; 43 this.year = year; 44 } 45 46 /** 47 * Initializes new date specified as a string in form MM/DD/YYYY. 48 * @param date the string representation of this date 49 * @throws IllegalArgumentException if this date is invalid 50 */ 51 public Date(String date) { 52 String[] fields = date.split("/"); 53 if (fields.length != 3) { 54 throw new IllegalArgumentException("Invalid date"); 55 } 56 month = Integer.parseInt(fields[0]); 57 day = Integer.parseInt(fields[1]); 58 year = Integer.parseInt(fields[2]); 59 if (!isValid(month, day, year)) throw new IllegalArgumentException("Invalid date"); 60 } 61 62 /** 63 * Return the month. 64 * @return the month (an integer between 1 and 12) 65 */ 66 public int month() { 67 return month; 68 } 69 70 /** 71 * Returns the day. 72 * @return the day (an integer between 1 and 31) 73 */ 74 public int day() { 75 return day; 76 } 77 78 /** 79 * Returns the year. 80 * @return the year 81 */ 82 public int year() { 83 return year; 84 } 85 86 87 // is the given date valid? 88 private static boolean isValid(int m, int d, int y) { 89 if (m < 1 || m > 12) return false; 90 if (d < 1 || d > DAYS[m]) return false; 91 if (m == 2 && d == 29 && !isLeapYear(y)) return false; 92 return true; 93 } 94 95 // is y a leap year? 96 private static boolean isLeapYear(int y) { 97 if (y % 400 == 0) return true; 98 if (y % 100 == 0) return false; 99 return y % 4 == 0; 100 } 101 102 /** 103 * Returns the next date in the calendar. 104 * 105 * @return a date that represents the next day after this day 106 */ 107 public Date next() { 108 if (isValid(month, day + 1, year)) return new Date(month, day + 1, year); 109 else if (isValid(month + 1, 1, year)) return new Date(month + 1, 1, year); 110 else return new Date(1, 1, year + 1); 111 } 112 113 /** 114 * Compares two dates chronologically. 115 * 116 * @param that the other date 117 * @return <tt>true</tt> if this date is after that date; <tt>false</tt> otherwise 118 */ 119 public boolean isAfter(Date that) { 120 return compareTo(that) > 0; 121 } 122 123 /** 124 * Compares two dates chronologically. 125 * 126 * @param that the other date 127 * @return <tt>true</tt> if this date is before that date; <tt>false</tt> otherwise 128 */ 129 public boolean isBefore(Date that) { 130 return compareTo(that) < 0; 131 } 132 133 /** 134 * Compares two dates chronologically. 135 * 136 * @return the value <tt>0</tt> if the argument date is equal to this date; 137 * a negative integer if this date is chronologically less than 138 * the argument date; and a positive ineger if this date is chronologically 139 * after the argument date 140 */ 141 @Override 142 public int compareTo(Date that) { 143 if (this.year < that.year) return -1; 144 if (this.year > that.year) return +1; 145 if (this.month < that.month) return -1; 146 if (this.month > that.month) return +1; 147 if (this.day < that.day) return -1; 148 if (this.day > that.day) return +1; 149 return 0; 150 } 151 152 /** 153 * Returns a string representation of this date. 154 * 155 * @return the string representation in the format MM/DD/YYYY 156 */ 157 @Override 158 public String toString() { 159 return month + "/" + day + "/" + year; 160 } 161 162 /** 163 * Compares this date to the specified date. 164 * 165 * @param other the other date 166 * @return <tt>true</tt> if this date equals <tt>other</tt>; <tt>false</tt> otherwise 167 */ 168 @Override 169 public boolean equals(Object other) { 170 if (other == this) return true; 171 if (other == null) return false; 172 if (other.getClass() != this.getClass()) return false; 173 Date that = (Date) other; 174 return (this.month == that.month) && (this.day == that.day) && (this.year == that.year); 175 } 176 177 /** 178 * Returns an integer hash code for this date. 179 * 180 * @return a hash code for this date 181 */ 182 @Override 183 public int hashCode() { 184 int hash = 17; 185 hash = 31*hash + month; 186 hash = 31*hash + day; 187 hash = 31*hash + year; 188 return hash; 189 } 190 191 /** 192 * Unit tests the <tt>Date</tt> data type. 193 */ 194 public static void main(String[] args) { 195 Date today = new Date(2, 25, 2004); 196 StdOut.println(today); 197 for (int i = 0; i < 10; i++) { 198 today = today.next(); 199 StdOut.println(today); 200 } 201 202 StdOut.println(today.isAfter(today.next())); 203 StdOut.println(today.isAfter(today)); 204 StdOut.println(today.next().isAfter(today)); 205 206 207 Date birthday = new Date(10, 16, 1971); 208 StdOut.println(birthday); 209 for (int i = 0; i < 10; i++) { 210 birthday = birthday.next(); 211 StdOut.println(birthday); 212 } 213 } 214 215 }