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