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: ymdValid = true; 017: julianValid = false; 018: } 019: 020: /** 021: Returns the year of this day 022: @return the year 023: */ 024: public int getYear() 025: { 026: ensureYmd(); 027: return year; 028: } 029: 030: /** 031: Returns the month of this day 032: @return the month 033: */ 034: public int getMonth() 035: { 036: ensureYmd(); 037: return month; 038: } 039: 040: /** 041: Returns the day of the month of this day 042: @return the day of the month 043: */ 044: public int getDate() 045: { 046: ensureYmd(); 047: return date; 048: } 049: 050: /** 051: Returns a day that is a certain number of days away from 052: this day 053: @param n the number of days, can be negative 054: @return a day that is n days away from this one 055: */ 056: public Day addDays(int n) 057: { 058: ensureJulian(); 059: return new Day(julian + n); 060: } 061: 062: /** 063: Returns the number of days between this day and another 064: day 065: @param other the other day 066: @return the number of days that this day is away from 067: the other (>0 if this day comes later) 068: */ 069: public int daysFrom(Day other) 070: { 071: ensureJulian(); 072: other.ensureJulian(); 073: return julian - other.julian; 074: } 075: 076: private Day(int aJulian) 077: { 078: julian = aJulian; 079: ymdValid = false; 080: julianValid = true; 081: } 082: 083: /** 084: Computes the Julian day number of this day if 085: necessary 086: */ 087: 088: private void ensureJulian() 089: { 090: if (julianValid) return; 091: julian = toJulian(year, month, date); 092: julianValid = true; 093: } 094: 095: /** 096: Converts this Julian day mumber to a calendar date if necessary. 097: */ 098: 099: private void ensureYmd() 100: { 101: if (ymdValid) return; 102: int[] ymd = fromJulian(julian); 103: year = ymd[0]; 104: month = ymd[1]; 105: date = ymd[2]; 106: ymdValid = true; 107: } 108: 109: /** 110: Computes the Julian day number of the given day day. 111: 112: @param year a year 113: @param month a month 114: @param date a date 115: @return The Julian day number that begins at noon of 116: the given day 117: Positive year signifies CE, negative year BCE. 118: Remember that the year after 1 BCE is 1 CE. 119: 120: A convenient reference point is that May 23, 1968 noon 121: is Julian day number 2440000. 122: 123: Julian day number 0 is a Monday. 124: 125: This algorithm is from Press et al., Numerical Recipes 126: in C, 2nd ed., Cambridge University Press 1992 127: */ 128: private static int toJulian(int year, int month, int date) 129: { 130: int jy = year; 131: if (year < 0) jy++; 132: int jm = month; 133: if (month > 2) jm++; 134: else 135: { 136: jy--; 137: jm += 13; 138: } 139: int jul = (int) (java.lang.Math.floor(365.25 * jy) 140: + java.lang.Math.floor(30.6001*jm) + date + 1720995.0); 141: 142: int IGREG = 15 + 31*(10+12*1582); 143: // Gregorian Calendar adopted Oct. 15, 1582 144: 145: if (date + 31 * (month + 12 * year) >= IGREG) 146: // change over to Gregorian calendar 147: { 148: int ja = (int)(0.01 * jy); 149: jul += 2 - ja + (int)(0.25 * ja); 150: } 151: return jul; 152: } 153: 154: /** 155: Converts a Julian day number to a calendar date. 156: 157: This algorithm is from Press et al., Numerical Recipes 158: in C, 2nd ed., Cambridge University Press 1992 159: 160: @param j the Julian day number 161: @return an array whose 0 entry is the year, 1 the month, 162: and 2 the day of the month. 163: */ 164: private static int[] fromJulian(int j) 165: { 166: int ja = j; 167: 168: int JGREG = 2299161; 169: /* the Julian day number of the adoption of the Gregorian 170: calendar 171: */ 172: 173: if (j >= JGREG) 174: /* cross-over to Gregorian Calendar produces this 175: correction 176: */ 177: { 178: int jalpha = (int)(((float)(j - 1867216) - 0.25) 179: / 36524.25); 180: ja += 1 + jalpha - (int)(0.25 * jalpha); 181: } 182: int jb = ja + 1524; 183: int jc = (int)(6680.0 + ((float)(jb-2439870) - 122.1) 184: /365.25); 185: int jd = (int)(365 * jc + (0.25 * jc)); 186: int je = (int)((jb - jd)/30.6001); 187: int date = jb - jd - (int)(30.6001 * je); 188: int month = je - 1; 189: if (month > 12) month -= 12; 190: int year = jc - 4715; 191: if (month > 2) --year; 192: if (year <= 0) --year; 193: return new int[] { year, month, date }; 194: } 195: 196: private int year; 197: private int month; 198: private int date; 199: private int julian; 200: private boolean ymdValid; 201: private boolean julianValid; 202: }