      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