1 /**
2 A Day object represents a day in the Julian/Gregorian calendar.
3 */
4 import java.util.GregorianCalendar;
5
6 public class Day
7 {
8 private int year;
9 private int month;
10 private int date;
11
12 private static final int[] DAYS_PER_MONTH
13 = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
14
15 private static final int GREGORIAN_START_YEAR = 1582;
16 private static final int GREGORIAN_START_MONTH = 10;
17 private static final int GREGORIAN_START_DAY = 15;
18 private static final int JULIAN_END_DAY = 4;
19
20 private static final int JANUARY = 1;
21 private static final int FEBRUARY = 2;
22 private static final int DECEMBER = 12;
23
24 /**
25 Constructs a day object representing today's date.
26 */
27 public Day()
28 {
29 GregorianCalendar today = new GregorianCalendar();
30 year = today.get(GregorianCalendar.YEAR);
31 month = today.get(GregorianCalendar.MONTH) + 1;
32 date = today.get(GregorianCalendar.DAY_OF_MONTH);
33 }
34
35 /**
36 Constructs a day with a given year, month, and day
37 of the Julian/Gregorian calendar. The Julian calendar
38 is used for all days before October 15, 1582
39 @param aYear a year != 0
40 @param aMonth a month between 1 and 12
41 @param aDate a date between 1 and 31
42 */
43 public Day(int aYear, int aMonth, int aDate)
44 {
45 year = aYear;
46 month = aMonth;
47 date = aDate;
48 }
49
50 /**
51 Returns the year of this day.
52 @return the year
53 */
54 public int getYear()
55 {
56 return year;
57 }
58
59 /**
60 Returns the month of this day.
61 @return the month
62 */
63 public int getMonth()
64 {
65 return month;
66 }
67
68 /**
69 Returns the day of the month of this day.
70 @return the day of the month
71 */
72 public int getDate()
73 {
74 return date;
75 }
76
77 /**
78 Returns a day that is a certain number of days away from
79 this day.
80 @param n the number of days, can be negative
81 @return a day that is n days away from this one
82 */
83 public Day addDays(int n)
84 {
85 Day result = this;
86 while (n > 0)
87 {
88 result = result.nextDay();
89 n--;
90 }
91 while (n < 0)
92 {
93 result = result.previousDay();
94 n++;
95 }
96 return result;
97 }
98
99 /**
100 Returns the number of days between this day and another
101 day.
102 @param other the other day
103 @return the number of days that this day is away from
104 the other (>0 if this day comes later than <code>other</code>)
105 */
106 public int daysFrom(Day other)
107 {
108 int n = 0;
109 Day d = this;
110 while (d.compareTo(other) > 0)
111 {
112 d = d.previousDay();
113 n++;
114 }
115 while (d.compareTo(other) < 0)
116 {
117 d = d.nextDay();
118 n--;
119 }
120 return n;
121 }
122
123 public String toString()
124 {
125 return String.format("%04d-%02d-%02d", year, month, date);
126 }
127
128 /**
129 Compares this day with another day.
130 @param other the other day
131 @return a positive number if this day comes after the
132 other day, a negative number if this day comes before
133 the other day, and zero if the days are the same
134 */
135 private int compareTo(Day other)
136 {
137 if (year > other.year) return 1;
138 if (year < other.year) return -1;
139 if (month > other.month) return 1;
140 if (month < other.month) return -1;
141 return date - other.date;
142 }
143
144 /**
145 Computes the next day.
146 @return the day following this day
147 */
148 private Day nextDay()
149 {
150 int y = year;
151 int m = month;
152 int d = date;
153
154 if (y == GREGORIAN_START_YEAR
155 && m == GREGORIAN_START_MONTH
156 && d == JULIAN_END_DAY)
157 d = GREGORIAN_START_DAY;
158 else if (d < daysPerMonth(y, m))
159 d++;
160 else
161 {
162 d = 1;
163 m++;
164 if (m > DECEMBER)
165 {
166 m = JANUARY;
167 y++;
168 if (y == 0) y++;
169 }
170 }
171 return new Day(y, m, d);
172 }
173
174 /**
175 Computes the previous day.
176 @return the day preceding this day
177 */
178 private Day previousDay()
179 {
180 int y = year;
181 int m = month;
182 int d = date;
183
184 if (y == GREGORIAN_START_YEAR
185 && m == GREGORIAN_START_MONTH
186 && d == GREGORIAN_START_DAY)
187 d = JULIAN_END_DAY;
188 else if (d > 1)
189 d--;
190 else
191 {
192 m--;
193 if (m < JANUARY)
194 {
195 m = DECEMBER;
196 y--;
197 if (y == 0) y--;
198 }
199 d = daysPerMonth(y, m);
200 }
201 return new Day(y, m, d);
202 }
203
204 /**
205 Gets the days in a given month.
206 @param y the year
207 @param m the month
208 @return the last day in the given month
209 */
210 private static int daysPerMonth(int y, int m)
211 {
212 int days = DAYS_PER_MONTH[m - 1];
213 if (m == FEBRUARY && isLeapYear(y))
214 days++;
215 return days;
216 }
217
218 /**
219 Tests if a year is a leap year.
220 @param y the year
221 @return true if y is a leap year
222 */
223 private static boolean isLeapYear(int y)
224 {
225 if (y % 4 != 0) return false;
226 if (y < GREGORIAN_START_YEAR) return true;
227 return (y % 100 != 0) || (y % 400 == 0);
228 }
229 }
230
231
232
233
234