001package horstmann.ch03_day2; 002public class Day 003{ 004 /** 005 Constructs a day with a given year, month, and day 006 of the Julian/Gregorian calendar. The Julian calendar 007 is used for all days before October 15, 1582 008 @param aYear a year != 0 009 @param aMonth a month between 1 and 12 010 @param aDate a date between 1 and 31 011 */ 012 public Day(int aYear, int aMonth, int aDate) 013 { 014 julian = toJulian(aYear, aMonth, aDate); 015 } 016 017 /** 018 Returns the year of this day 019 @return the year 020 */ 021 public int getYear() 022 { 023 return fromJulian(julian)[0]; 024 } 025 026 /** 027 Returns the month of this day 028 @return the month 029 */ 030 public int getMonth() 031 { 032 return fromJulian(julian)[1]; 033 } 034 035 /** 036 Returns the day of the month of this day 037 @return the day of the month 038 */ 039 public int getDate() 040 { 041 return fromJulian(julian)[2]; 042 } 043 044 /** 045 Returns a day that is a certain number of days away from 046 this day 047 @param n the number of days, can be negative 048 @return a day that is n days away from this one 049 */ 050 public Day addDays(int n) 051 { 052 return new Day(julian + n); 053 } 054 055 /** 056 Returns the number of days between this day and another day. 057 @param other the other day 058 @return the number of days that this day is away from 059 the other (>0 if this day comes later) 060 */ 061 public int daysFrom(Day other) 062 { 063 return julian - other.julian; 064 } 065 066 private Day(int aJulian) 067 { 068 julian = aJulian; 069 } 070 071 /** 072 Computes the Julian day number of the given day. 073 @param year a year 074 @param month a month 075 @param date a day of the month 076 @return The Julian day number that begins at noon of 077 the given day 078 Positive year signifies CE, negative year BCE. 079 Remember that the year after 1 BCE was 1 CE. 080 081 A convenient reference point is that May 23, 1968 noon 082 is Julian day number 2440000. 083 084 Julian day number 0 is a Monday. 085 086 This algorithm is from Press et al., Numerical Recipes 087 in C, 2nd ed., Cambridge University Press 1992 088 */ 089 private static int toJulian(int year, int month, int date) 090 { 091 int jy = year; 092 if (year < 0) jy++; 093 int jm = month; 094 if (month > 2) jm++; 095 else 096 { 097 jy--; 098 jm += 13; 099 } 100 int jul = (int) (java.lang.Math.floor(365.25 * jy) 101 + java.lang.Math.floor(30.6001 * jm) + date + 1720995.0); 102 103 int IGREG = 15 + 31 * (10 + 12 * 1582); 104 // Gregorian Calendar adopted Oct. 15, 1582 105 106 if (date + 31 * (month + 12 * year) >= IGREG) 107 // Change over to Gregorian calendar 108 { 109 int ja = (int) (0.01 * jy); 110 jul += 2 - ja + (int) (0.25 * ja); 111 } 112 return jul; 113 } 114 115 /** 116 Converts a Julian day number to a calendar date. 117 118 This algorithm is from Press et al., Numerical Recipes 119 in C, 2nd ed., Cambridge University Press 1992 120 121 @param j the Julian day number 122 @return an array whose 0 entry is the year, 1 the month, 123 and 2 the day of the month. 124 */ 125 @SuppressWarnings("cast") 126 private static int[] fromJulian(int j) 127 { 128 int ja = j; 129 130 int JGREG = 2299161; 131 // The Julian day number of the adoption of the Gregorian calendar 132 133 if (j >= JGREG) 134 // Cross-over to Gregorian Calendar produces this correction 135 { 136 int jalpha = (int) (((float) (j - 1867216) - 0.25) 137 / 36524.25); 138 ja += 1 + jalpha - (int) (0.25 * jalpha); 139 } 140 int jb = ja + 1524; 141 int jc = (int) (6680.0 + ((float) (jb - 2439870) - 122.1) 142 / 365.25); 143 int jd = (int) (365 * jc + (0.25 * jc)); 144 int je = (int) ((jb - jd) / 30.6001); 145 int date = jb - jd - (int) (30.6001 * je); 146 int month = je - 1; 147 if (month > 12) month -= 12; 148 int year = jc - 4715; 149 if (month > 2) --year; 150 if (year <= 0) --year; 151 return new int[] { year, month, date }; 152 } 153 154 private int julian; 155} 156 157 158 159 160