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; y++;
130: if (y == 0) y++;
131: }
132: }
133: return new Day(y, m, d);
134: }
136: /**
137: Computes the previous day.
138: @return the day preceding this day
139: */
140: private Day previousDay()
141: {
142: int y = year;
143: int m = month;
144: int d = date;
146: if (y == GREGORIAN_START_YEAR
147: && m == GREGORIAN_START_MONTH
148: && d == GREGORIAN_START_DAY)
149: d = JULIAN_END_DAY;
150: else if (d > 1)
151: d--;
152: else
153: {
154: m--;
155: if (m < JANUARY)
156: {
157: m = DECEMBER; y--;
158: if (y == 0) y = -1;
159: }
160: d = daysPerMonth(y, m);
161: }
162: return new Day(y, m, d);
163: }
165: /**
166: Gets the days in a given month
167: @param y the year
168: @param m the month
169: @return the last day in the given month
170: */
171: private static int daysPerMonth(int y, int m)
172: {
173: int days = DAYS_PER_MONTH[m - 1];
174: if (m == FEBRUARY && isLeapYear(y))
175: days++;
176: return days;
177: }
179: /**
180: Tests if a year is a leap year
181: @param y the year
182: @return true if y is a leap year
183: */
184: private static boolean isLeapYear(int y)
185: {
186: if (y % 4 != 0) return false;
187: if (y < GREGORIAN_START_YEAR) return true;
188: return (y % 100 != 0) || (y % 400 == 0);
189: }
191: private int year;
192: private int month;
193: private int date;
195: private static final int[] DAYS_PER_MONTH
196: = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
198: private static final int GREGORIAN_START_YEAR = 1582;
199: private static final int GREGORIAN_START_MONTH = 10;
200: private static final int GREGORIAN_START_DAY = 15;
201: private static final int JULIAN_END_DAY = 4;
203: public static final int JANUARY = 1;
204: public static final int FEBRUARY = 2;
205: public static final int DECEMBER = 12;
206: }