1  /**
  2     A Day object represents a day in the Julian/Gregorian calendar.
  3  */
  4  import java.util.GregorianCalendar;
  5  
  6  public class Day
  7  {
  8     private int year;
  9     private int month;
 10     private int date;
 11  
 12     private static final int[] DAYS_PER_MONTH 
 13           = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
 14  
 15     private static final int GREGORIAN_START_YEAR = 1582;
 16     private static final int GREGORIAN_START_MONTH = 10;
 17     private static final int GREGORIAN_START_DAY = 15;
 18     private static final int JULIAN_END_DAY = 4;
 19  
 20     private static final int JANUARY = 1;
 21     private static final int FEBRUARY = 2;
 22     private static final int DECEMBER = 12;
 23  
 24     /**
 25        Constructs a day object representing today's date.
 26     */
 27     public Day()
 28     {
 29        GregorianCalendar today = new GregorianCalendar();
 30        year = today.get(GregorianCalendar.YEAR);
 31        month = today.get(GregorianCalendar.MONTH) + 1;
 32        date = today.get(GregorianCalendar.DAY_OF_MONTH);
 33     }
 34  
 35     /**
 36        Constructs a day with a given year, month, and day
 37        of the Julian/Gregorian calendar. The Julian calendar
 38        is used for all days before October 15, 1582
 39        @param aYear a year != 0
 40        @param aMonth a month between 1 and 12
 41        @param aDate a date between 1 and 31
 42     */
 43     public Day(int aYear, int aMonth, int aDate)
 44     {
 45        year = aYear;
 46        month = aMonth;
 47        date = aDate;
 48     }
 49  
 50     /**
 51        Returns the year of this day.
 52        @return the year
 53     */
 54     public int getYear()
 55     {
 56        return year;
 57     }
 58  
 59     /**
 60        Returns the month of this day.
 61        @return the month
 62     */
 63     public int getMonth()
 64     {
 65        return month;
 66     }
 67  
 68     /**
 69        Returns the day of the month of this day.
 70        @return the day of the month
 71     */
 72     public int getDate()
 73     {
 74        return date;
 75     }
 76  
 77     /**
 78        Returns a day that is a certain number of days away from
 79        this day.
 80        @param n the number of days, can be negative
 81        @return a day that is n days away from this one
 82     */
 83     public Day addDays(int n)
 84     {
 85        Day result = this;
 86        while (n > 0)
 87        {
 88           result = result.nextDay();
 89           n--;
 90        }
 91        while (n < 0)
 92        {
 93           result = result.previousDay();
 94           n++;
 95        }
 96        return result;
 97     }
 98  
 99     /**
100        Returns the number of days between this day and another
101        day.
102        @param other the other day
103        @return the number of days that this day is away from 
104        the other (>0 if this day comes later than <code>other</code>)
105     */
106     public int daysFrom(Day other)
107     {
108        int n = 0;
109        Day d = this;
110        while (d.compareTo(other) > 0)
111        {
112           d = d.previousDay();
113           n++;
114        }
115        while (d.compareTo(other) < 0)
116        {
117           d = d.nextDay();
118           n--;
119        }
120        return n;
121     }
122  
123     public String toString()
124     {
125        return String.format("%04d-%02d-%02d", year, month, date);
126     }
127  
128     /**
129        Compares this day with another day.
130        @param other the other day
131        @return a positive number if this day comes after the
132        other day, a negative number if this day comes before
133        the other day, and zero if the days are the same
134     */
135     private int compareTo(Day other)
136     {
137        if (year > other.year) return 1;
138        if (year < other.year) return -1;
139        if (month > other.month) return 1;
140        if (month < other.month) return -1;
141        return date - other.date;
142     }
143  
144     /**
145        Computes the next day.
146        @return the day following this day
147     */
148     private Day nextDay()
149     {
150        int y = year;
151        int m = month;
152        int d = date;
153  
154        if (y == GREGORIAN_START_YEAR
155              && m == GREGORIAN_START_MONTH
156              && d == JULIAN_END_DAY)
157           d = GREGORIAN_START_DAY;
158        else if (d < daysPerMonth(y, m))
159           d++;
160        else
161        {
162           d = 1;
163           m++;
164           if (m > DECEMBER) 
165           { 
166              m = JANUARY; 
167              y++; 
168              if (y == 0) y++;
169           }
170        }
171        return new Day(y, m, d);
172     }
173  
174     /**
175        Computes the previous day.
176        @return the day preceding this day
177     */
178     private Day previousDay()
179     {
180        int y = year;
181        int m = month;
182        int d = date;
183  
184        if (y == GREGORIAN_START_YEAR
185              && m == GREGORIAN_START_MONTH
186              && d == GREGORIAN_START_DAY)
187           d = JULIAN_END_DAY;
188        else if (d > 1)
189           d--;
190        else
191        {	
192           m--;
193           if (m < JANUARY) 
194           {             
195              m = DECEMBER; 
196              y--; 
197              if (y == 0) y--;
198           }
199           d = daysPerMonth(y, m);
200        }
201        return new Day(y, m, d);
202     }
203  
204     /**
205        Gets the days in a given month.
206        @param y the year
207        @param m the month
208        @return the last day in the given month
209     */
210     private static int daysPerMonth(int y, int m)
211     {
212        int days = DAYS_PER_MONTH[m - 1];
213        if (m == FEBRUARY && isLeapYear(y)) 
214           days++;
215        return days;
216     }
217  
218     /**
219        Tests if a year is a leap year.
220        @param y the year
221        @return true if y is a leap year
222     */
223     private static boolean isLeapYear(int y)
224     {
225        if (y % 4 != 0) return false;
226        if (y < GREGORIAN_START_YEAR) return true;
227        return (y % 100 != 0) || (y % 400 == 0);
228     }
229  }
230  
231  
232  
233  
234