001: public class Day
002: {
003: /**
004: Constructs a day with a given year, month, and day
005: of the Julian/Gregorian calendar. The Julian calendar
006: is used for all days before October 15, 1582
007: @param aYear a year != 0
008: @param aMonth a month between 1 and 12
009: @param aDate a date between 1 and 31
010: */
011: public Day(int aYear, int aMonth, int aDate)
012: {
013: year = aYear;
014: month = aMonth;
015: date = aDate;
016: }
017:
018: /**
019: Returns the year of this day
020: @return the year
021: */
022: public int getYear()
023: {
024: return year;
025: }
026:
027: /**
028: Returns the month of this day
029: @return the month
030: */
031: public int getMonth()
032: {
033: return month;
034: }
035:
036: /**
037: Returns the day of the month of this day
038: @return the day of the month
039: */
040: public int getDate()
041: {
042: return date;
043: }
044:
045: /**
046: Returns a day that is a certain number of days away from
047: this day
048: @param n the number of days, can be negative
049: @return a day that is n days away from this one
050: */
051: public Day addDays(int n)
052: {
053: Day result = this;
054: while (n > 0)
055: {
056: result = result.nextDay();
057: n--;
058: }
059: while (n < 0)
060: {
061: result = result.previousDay();
062: n++;
063: }
064: return result;
065: }
066:
067: /**
068: Returns the number of days between this day and another
069: day
070: @param other the other day
071: @return the number of days that this day is away from
072: the other (>0 if this day comes later)
073: */
074: public int daysFrom(Day other)
075: {
076: int n = 0;
077: Day d = this;
078: while (d.compareTo(other) > 0)
079: {
080: d = d.previousDay();
081: n++;
082: }
083: while (d.compareTo(other) < 0)
084: {
085: d = d.nextDay();
086: n--;
087: }
088: return n;
089: }
090:
091: /**
092: Compares this day with another day.
093: @param other the other day
094: @return a positive number if this day comes after the
095: other day, a negative number if this day comes before
096: the other day, and zero if the days are the same
097: */
098: private int compareTo(Day other)
099: {
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: }
106:
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;
116:
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: }
136:
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;
146:
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: }
166:
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: }
180:
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: }
192:
193: private int year;
194: private int month;
195: private int date;
196:
197: private static final int[] DAYS_PER_MONTH
198: = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
199:
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;
204:
205: public static final int JANUARY = 1;
206: public static final int FEBRUARY = 2;
207: public static final int DECEMBER = 12;
208: }
209:
210:
211:
212:
213: