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     }
 17  
 18     /**
 19        Returns the year of this day
 20        @return the year
 21     */
 22     public int getYear()
 23     {
 24        return year;
 25     }
 26  
 27     /**
 28        Returns the month of this day
 29        @return the month
 30     */
 31     public int getMonthValue()
 32     {
 33        return month;
 34     }
 35  
 36     /**
 37        Returns the day of the month of this day
 38        @return the day of the month
 39     */
 40     public int getDayOfMonth()
 41     {
 42        return date;
 43     }
 44  
 45     /**
 46        Returns a day that is a certain number of days away from
 47        this day
 48        @param n the number of days, can be negative
 49        @return a day that is n days away from this one
 50     */
 51     public Day plusDays(int n)
 52     {
 53        Day result = this;
 54        while (n > 0)
 55        {
 56           result = result.nextDay();
 57           n--;
 58        }
 59        while (n < 0)
 60        {
 61           result = result.previousDay();
 62           n++;
 63        }
 64        return result;
 65     }
 66  
 67     /**
 68        Returns the number of days between this day and another
 69        day
 70        @param other the other day
 71        @return the number of days that this day is away from 
 72        the other (>0 if this day comes later)
 73     */
 74     public int daysFrom(Day other)
 75     {
 76        int n = 0;
 77        Day d = this;
 78        while (d.compareTo(other) > 0)
 79        {
 80           d = d.previousDay();
 81           n++;
 82        }
 83        while (d.compareTo(other) < 0)
 84        {
 85           d = d.nextDay();
 86           n--;
 87        }
 88        return n;
 89     }
 90  
 91     /**
 92        Compares this day with another day.
 93        @param other the other day
 94        @return a positive number if this day comes after the
 95        other day, a negative number if this day comes before
 96        the other day, and zero if the days are the same
 97     */
 98     private int compareTo(Day other)
 99     {
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