1  public class Day
  2  {
  3     /**
  4        Constructs a day with a given year, month, and day
  5        of the Julian/Gregorian calendar. The Julian calendar
  6        is used for all days before October 15, 1582
  7        @param aYear a year != 0
  8        @param aMonth a month between 1 and 12
  9        @param aDayOfMonth a day of the month between 1 and 31
 10     */
 11     public Day(int aYear, int aMonth, int aDayOfMonth)
 12     {
 13        year = aYear;
 14        month = aMonth;
 15        date = aDayOfMonth;
 16        ymdValid = true;
 17        julianValid = false;
 18     }
 19  
 20     /**
 21        Returns the year of this day
 22        @return the year
 23     */
 24     public int getYear()
 25     {
 26        ensureYmd();
 27        return year;
 28     }
 29  
 30     /**
 31        Returns the month of this day
 32        @return the month
 33     */
 34     public int getMonthValue()
 35     {
 36        ensureYmd();
 37        return month;
 38     }
 39  
 40     /**
 41        Returns the day of the month of this day
 42        @return the day of the month
 43     */
 44     public int getDayOfMonth()
 45     {
 46        ensureYmd();
 47        return date;
 48     }
 49  
 50     /**
 51        Returns a day that is a certain number of days away from
 52        this day
 53        @param n the number of days, can be negative
 54        @return a day that is n days away from this one
 55     */
 56     public Day plusDays(int n)
 57     {
 58        ensureJulian();
 59        return new Day(julian + n);
 60     }
 61  
 62     /**
 63        Returns the number of days between this day and another
 64        day
 65        @param other the other day
 66        @return the number of days that this day is away from 
 67        the other (>0 if this day comes later)
 68     */
 69     public int daysFrom(Day other)
 70     {
 71        ensureJulian();
 72        other.ensureJulian();
 73        return julian - other.julian;
 74     }
 75  
 76     private Day(int aJulian)
 77     {
 78        julian = aJulian;
 79        ymdValid = false;
 80        julianValid = true;
 81     }
 82  
 83     /**
 84        Computes the Julian day number of this day if 
 85        necessary
 86     */
 87     private void ensureJulian()
 88     {  
 89        if (julianValid) return;
 90        julian = toJulian(year, month, date);
 91        julianValid = true;
 92     }
 93  
 94     /**
 95        Converts this Julian day mumber to a calendar date if necessary.
 96     */
 97     private void ensureYmd()
 98     {  
 99        if (ymdValid) return;
100        int[] ymd = fromJulian(julian);
101        year = ymd[0];
102        month = ymd[1];
103        date = ymd[2];
104        ymdValid = true;
105     }
106  
107     /**
108        Computes the Julian day number of the given day day.
109  
110        @param year a year
111        @param month a month
112        @param date a day of the month
113        @return The Julian day number that begins at noon of 
114        the given day
115        Positive year signifies CE, negative year BCE. 
116        Remember that the year after 1 BCE is 1 CE.
117  
118        A convenient reference point is that May 23, 1968 noon
119        is Julian day number 2440000.
120  
121        Julian day number 0 is a Monday.
122  
123        This algorithm is from Press et al., Numerical Recipes
124        in C, 2nd ed., Cambridge University Press 1992
125     */
126     private static int toJulian(int year, int month, int date)
127     {  
128        int jy = year;
129        if (year < 0) jy++;
130        int jm = month;
131        if (month > 2) jm++;
132        else
133        {  
134           jy--;
135           jm += 13;
136        }
137        int jul = (int) (java.lang.Math.floor(365.25 * jy) 
138              + java.lang.Math.floor(30.6001 * jm) + date + 1720995.0);
139  
140        int IGREG = 15 + 31 * (10 + 12 * 1582);
141           // Gregorian Calendar adopted Oct. 15, 1582
142  
143        if (date + 31 * (month + 12 * year) >= IGREG)
144           // Change over to Gregorian calendar
145        {  
146           int ja = (int) (0.01 * jy);
147           jul += 2 - ja + (int) (0.25 * ja);
148        }
149        return jul;
150     }
151  
152     /**
153        Converts a Julian day number to a calendar date.
154        
155        This algorithm is from Press et al., Numerical Recipes
156        in C, 2nd ed., Cambridge University Press 1992
157  
158        @param j  the Julian day number
159        @return an array whose 0 entry is the year, 1 the month,
160        and 2 the day of the month.
161     */
162     private static int[] fromJulian(int j)
163     {  
164        int ja = j;
165     
166        int JGREG = 2299161;
167           // The Julian day number of the adoption of the Gregorian calendar    
168  
169        if (j >= JGREG)
170           // Cross-over to Gregorian Calendar produces this correction
171        {  
172           int jalpha = (int) (((float) (j - 1867216) - 0.25) 
173               / 36524.25);
174           ja += 1 + jalpha - (int) (0.25 * jalpha);
175        }
176        int jb = ja + 1524;
177        int jc = (int) (6680.0 + ((float) (jb - 2439870) - 122.1)
178            / 365.25);
179        int jd = (int) (365 * jc + (0.25 * jc));
180        int je = (int) ((jb - jd) / 30.6001);
181        int date = jb - jd - (int) (30.6001 * je);
182        int month = je - 1;
183        if (month > 12) month -= 12;
184        int year = jc - 4715;
185        if (month > 2) --year;
186        if (year <= 0) --year;
187        return new int[] { year, month, date };
188     }
189  
190     private int year;
191     private int month;
192     private int date;
193     private int julian;
194     private boolean ymdValid;
195     private boolean julianValid;
196  }
197  
198  
199  
200  
201