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: private static final int JANUARY = 1; 206: private static final int FEBRUARY = 2; 207: private static final int DECEMBER = 12; 208: } 209: 210: 211: 212: 213: