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