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; y++; 130: if (y == 0) y++; 131: } 132: } 133: return new Day(y, m, d); 134: } 135: 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; 145: 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: } 164: 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: } 178: 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: } 190: 191: private int year; 192: private int month; 193: private int date; 194: 195: private static final int[] DAYS_PER_MONTH 196: = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; 197: 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; 202: 203: public static final int JANUARY = 1; 204: public static final int FEBRUARY = 2; 205: public static final int DECEMBER = 12; 206: } 207: 208: 209: 210: 211: