001// Exercise 1.2.19 (Solution published at http://algs4.cs.princeton.edu/) 002package algs12; 003import java.util.Arrays; 004import java.util.Comparator; 005import stdlib.*; 006/* *********************************************************************** 007 * Compilation: javac Date.java 008 * Execution: java Date 009 * 010 * An immutable data type for dates. 011 * 012 *************************************************************************/ 013 014public class Date implements Comparable<Date> { 015 private static final int[] DAYS = { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; 016 017 private final int month; // month (between 1 and 12) 018 private final int day; // day (between 1 and DAYS[month] 019 private final int year; // year 020 021 // do bounds-checking to ensure object represents a valid date 022 public Date(int month, int day, int year) { 023 if (!isValid(month, day, year)) throw new Error("Invalid date"); 024 this.month = month; 025 this.day = day; 026 this.year = year; 027 } 028 029 // create new data by parsing from string of the form mm/dd/yy 030 public Date(String date) { 031 String[] fields = date.split("/"); 032 if (fields.length != 3) { 033 throw new Error("Date parse error"); 034 } 035 month = Integer.parseInt(fields[0]); 036 day = Integer.parseInt(fields[1]); 037 year = Integer.parseInt(fields[2]); 038 if (!isValid(month, day, year)) throw new Error("Invalid date"); 039 } 040 041 public int month() { return month; } 042 public int day() { return day; } 043 public int year() { return year; } 044 045 046 // is the given date valid? 047 private static boolean isValid(int m, int d, int y) { 048 if (m < 1 || m > 12) return false; 049 if (d < 1 || d > DAYS[m]) return false; 050 if (m == 2 && d == 29 && !isLeapYear(y)) return false; 051 return true; 052 } 053 054 // is y a leap year? 055 private static boolean isLeapYear(int y) { 056 if (y % 400 == 0) return true; 057 if (y % 100 == 0) return false; 058 return y % 4 == 0; 059 } 060 061 // return the next Date 062 public Date next() { 063 if (isValid(month, day + 1, year)) return new Date(month, day + 1, year); 064 else if (isValid(month + 1, 1, year)) return new Date(month + 1, 1, year); 065 else return new Date(1, 1, year + 1); 066 } 067 068 069 // is this Date after b? 070 public boolean isAfter(Date b) { 071 return compareTo(b) > 0; 072 } 073 074 // is this Date a before b? 075 public boolean isBefore(Date b) { 076 return compareTo(b) < 0; 077 } 078 079 // compare this Date to that one 080 public int compareTo(Date that) { 081 if (this.year < that.year) return -1; 082 if (this.year > that.year) return +1; 083 if (this.month < that.month) return -1; 084 if (this.month > that.month) return +1; 085 if (this.day < that.day) return -1; 086 if (this.day > that.day) return +1; 087 return 0; 088 } 089 090 // return a string representation of this date 091 public String toString() { 092 return month + "/" + day + "/" + year; 093 } 094 095 // is this Date equal to x? 096 public boolean equals(Object x) { 097 if (x == this) return true; 098 if (x == null) return false; 099 if (x.getClass() != this.getClass()) return false; 100 Date that = (Date) x; 101 return (this.month == that.month) && (this.day == that.day) && (this.year == that.year); 102 } 103 104 public int hashCode() { 105 int hash = 17; 106 hash = 31*hash + Integer.hashCode (month); 107 hash = 31*hash + Integer.hashCode (day); 108 hash = 31*hash + Integer.hashCode (year); 109 return hash; 110 } 111 112 113 114 // A stupid class! 115 private static class MyComp implements Comparator<Date>{ 116 public int compare (Date o1, Date o2) { 117 return o2.compareTo (o1); 118 } 119 } 120 121 // sample client for testing 122 public static void main(String[] args) { 123 // using the stupid class: 124 Comparator<Date> c1 = new MyComp (); 125 126 // using an inner class: 127 Comparator<Date> c2 = new Comparator<Date>() { 128 public int compare (Date o1, Date o2) { 129 return o2.compareTo (o1); 130 } 131 }; 132 133 // using a lambda expression: 134 Comparator<Date> c3 = (o1, o2) -> o2.compareTo (o1); 135 136 Date[] dates = new Date[] { new Date(2, 25, 2004), new Date(2, 25, 2003), } ; 137 StdOut.println (Arrays.binarySearch (dates, new Date(2, 25, 2003), c1)); 138 139// Date today = new Date(2, 25, 2004); 140// StdOut.println(today); 141// for (int i = 0; i < 10; i++) { 142// today = today.next(); 143// StdOut.println(today); 144// } 145// 146// StdOut.println(today.isAfter(today.next())); 147// StdOut.println(today.isAfter(today)); 148// StdOut.println(today.next().isAfter(today)); 149// 150// 151// Date birthday = new Date(10, 16, 1971); 152// StdOut.println(birthday); 153// for (int i = 0; i < 10; i++) { 154// birthday = birthday.next(); 155// StdOut.println(birthday); 156// } 157 } 158 159}