001    /**
002     * Copyright 2010 The Kuali Foundation Licensed under the
003     * Educational Community License, Version 2.0 (the "License"); you may
004     * not use this file except in compliance with the License. You may
005     * obtain a copy of the License at
006     *
007     * http://www.osedu.org/licenses/ECL-2.0
008     *
009     * Unless required by applicable law or agreed to in writing,
010     * software distributed under the License is distributed on an "AS IS"
011     * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
012     * or implied. See the License for the specific language governing
013     * permissions and limitations under the License.
014     */
015    
016    package org.kuali.student.lum.common.client.widgets;
017    
018    import java.util.Date;
019    
020    /**
021     * <dl>
022     * <dt><b>Title: </b><dd>GregorianCalendar</dd>
023     * <p>
024     * <dt><b>Description: </b><dd>java.util.GregorianCalendar replacment</dd>
025     * </dl>
026     * @author <a href="mailto:andre.freller@gmail.com">Andre Freller</a>
027     * @version $Revision: 0.1 $
028     */
029    ///////// ///////// ///////// ///////// ///////// ///////// ///////// ///////// ///////// ///////// ///////// /////////
030    public class GregorianCalendar extends Calendar
031    {
032        public static final int BC          = 0;
033        public static final int AD          = 1;
034    
035        public GregorianCalendar() {
036            super();
037        }
038        public GregorianCalendar(Date date) {
039            setTime(date);
040        }
041        public GregorianCalendar(int year, int month, int date) {
042            set(year, month, date);
043        }
044        public GregorianCalendar(int year, int month, int date, int hour) {
045            set(year, month, date, hour);
046        }
047        public GregorianCalendar(int year, int month, int date, int hour, int minute) {
048            set(year, month, date, hour, minute);
049        }
050        public GregorianCalendar(int year, int month, int date, int hour, int minute, int second) {
051            set(year, month, date, hour, minute, second);
052        }
053    
054        protected static int[] daysInMonth  = {31, 28, 31, 30, 31, 30, 31, 31 ,30, 31, 30, 31};
055        public static int getMaxDaysInMonth(int year, int month) {
056            if (month == Calendar.FEBRUARY  &&  isLeapYear(year))
057                return daysInMonth[month] + 1;
058            else
059                return daysInMonth[month];
060        }
061        public int getMaxDaysInMonth() {
062            return getMaxDaysInMonth(this.year, this.month);
063        }
064    
065        public static int getNumOfWeeksInMonth(int year, int month, int firstDayOfWeek) {
066            int day1        = getWeekDay(year, month, 1);
067            int maxDays     = getMaxDaysInMonth(year, month);
068            if (month == Calendar.FEBRUARY  &&  !isLeapYear(year)  &&  day1 == firstDayOfWeek)
069                return 4;
070            if (maxDays == 30  &&  (day1 > firstDayOfWeek + 5  ||  day1 < firstDayOfWeek))
071                return 6;
072            if (maxDays == 31  &&  (day1 > firstDayOfWeek + 4  ||  day1 < firstDayOfWeek))
073                return 6;
074            return 5;
075        }
076        public int getNumOfWeeksInMonth() {
077            return getNumOfWeeksInMonth(this.year, this.month, this.firstWeekDayOfWeek);
078        }
079    
080        public static int getWeekDay(int year, int month, int dayOfMonth) {
081            int weekDay     = year - 1900;
082            weekDay         += weekDay/4;
083            weekDay         %= 7;
084            if (month <= Calendar.FEBRUARY  &&  isLeapYear(weekDay))
085                weekDay     -= 1;
086            weekDay         += dayOfMonth;
087            weekDay         %= 7;
088            if (month == Calendar.MAY)
089                weekDay     += 1;
090            else if (month == Calendar.AUGUST)
091                weekDay     += 2;
092            else if (month == Calendar.FEBRUARY  ||  month == Calendar.MARCH  ||  month == Calendar.NOVEMBER)
093                weekDay     += 3;
094            else if (month == Calendar.JUNE)
095                weekDay     += 4;
096            else if (month == Calendar.SEPTEMBER  ||  month == Calendar.DECEMBER)
097                weekDay     += 5;
098            else if (month == Calendar.APRIL  ||  month == Calendar.JULY)
099                weekDay     += 6;
100            weekDay         %= 7;
101    
102            return Calendar.SUNDAY + weekDay;
103        }
104        public int getWeekDay() {
105            return getWeekDay(this.year, this.month, this.dayOfMonth);
106        }
107        public int getFirstWeekDayOfMonth() {
108            return getWeekDay(this.year, this.month, 1);
109        }
110    
111        // Gets the minimum value for the given time field.
112        public int getMinimum(int fieldCode) {
113            switch (fieldCode) {
114            case Calendar.MILLISECOND:
115                return 0;
116            case Calendar.SECOND:
117                return 0;
118            case Calendar.MINUTE:
119                return 0;
120            case Calendar.HOUR:
121                return 0;
122            case Calendar.HOUR_OF_DAY:
123                return 0;
124            case Calendar.DATE:
125                return 1;
126            case Calendar.MONTH:
127                return Calendar.JANUARY;
128            default:
129                return -1;
130            }
131        }
132        // Return the minimum value that this field could have, given the current date.
133        public int getActualMinimum(int fieldCode) {
134            return getMinimum(fieldCode);
135        }
136        // Gets the highest minimum value for the given field if varies.
137        public   int getGreatestMinimum(int fieldCode) {
138            return getMinimum(fieldCode);
139        }
140    
141        // Gets the maximum value for the given time field.
142        public   int getMaximum(int fieldCode) {
143            switch (fieldCode) {
144            case Calendar.MILLISECOND:
145                return 999;
146            case Calendar.SECOND:
147                return 59;
148            case Calendar.MINUTE:
149                return 59;
150            case Calendar.HOUR:
151                return 11;
152            case Calendar.HOUR_OF_DAY:
153                return 23;
154            case Calendar.DATE:
155                return 31;
156            case Calendar.MONTH:
157                return Calendar.DECEMBER;
158            default:
159                return -1;
160            }
161        }
162        // Return the maximum value that this field could have, given the current date.
163        public int getActualMaximum(int fieldCode) {
164            switch (fieldCode) {
165            case Calendar.MILLISECOND:
166                return 999;
167            case Calendar.SECOND:
168                return 59;
169            case Calendar.MINUTE:
170                return 59;
171            case Calendar.HOUR:
172                return 11;
173            case Calendar.HOUR_OF_DAY:
174                return 23;
175            case Calendar.DATE:
176                return getMaxDaysInMonth();
177            case Calendar.MONTH:
178                return Calendar.DECEMBER;
179            default:
180                return -1;
181            }
182        }
183        // Gets the lowest maximum value for the given field if varies.
184        public   int getLeastMaximum(int fieldCode) {
185            switch (fieldCode) {
186            case Calendar.MILLISECOND:
187                return 999;
188            case Calendar.SECOND:
189                return 59;
190            case Calendar.MINUTE:
191                return 59;
192            case Calendar.HOUR:
193                return 11;
194            case Calendar.HOUR_OF_DAY:
195                return 23;
196            case Calendar.DATE:
197                return 28;
198            case Calendar.MONTH:
199                return Calendar.DECEMBER;
200            default:
201                return -1;
202            }
203        }
204    
205    
206        public void set(int fieldCode, int value) {
207            switch (fieldCode) {
208            case Calendar.SECOND:
209                this.second         = value;
210                break;
211            case Calendar.MINUTE:
212                this.minute         = value;
213                break;
214            case Calendar.HOUR:
215                this.hour           = value;
216                break;
217            case Calendar.HOUR_OF_DAY:
218                if (value <= 12) {
219                    this.hour       = value;
220                    this.amPm       = Calendar.AM;
221                } else {
222                    this.hour       = value - 12;
223                    this.amPm       = Calendar.PM;
224                }
225                break;
226            case Calendar.DATE:
227                this.dayOfMonth             = value;
228                break;
229            case Calendar.MONTH:
230                this.month          = value;
231                if (this.dayOfMonth > getMaxDaysInMonth())
232                    this.dayOfMonth = getMaxDaysInMonth();
233                break;
234            case Calendar.YEAR:
235                this.year           = value;
236                break;
237            case Calendar.AM_PM:
238                this.amPm           = value;
239                break;
240            }
241            computeTime();
242        }
243    
244    
245        // Date Arithmetic function.
246        public void add(int fieldCode, int amount) {
247            switch (fieldCode) {
248            case Calendar.DATE:
249                amount              *= 24;
250            case Calendar.HOUR:
251                amount              *= 60;
252            case Calendar.MINUTE:
253                amount              *= 60;
254            case Calendar.SECOND:
255                amount              *= 1000;
256            case Calendar.MILLISECOND:
257                this.date.setTime(this.date.getTime() + amount);
258                computeFields();
259                break;
260            case Calendar.MONTH:
261                this.year           += (this.month + amount) / 12;
262                this.month          = (this.month + amount) % 12;
263                if (this.month < 0) {
264                    this.year       -= 1;
265                    this.month      += 12;
266                }
267                if (this.dayOfMonth > getMaxDaysInMonth())
268                    this.dayOfMonth = getMaxDaysInMonth();
269                computeTime();
270                break;
271            case Calendar.YEAR:
272                this.year           += amount;
273                computeTime();
274                break;
275            }
276        }
277    
278        // Time Field Rolling function.
279        public void roll(int fieldCode, int amount) {
280            switch (fieldCode) {
281            case Calendar.SECOND:
282                this.second         = (this.second + amount) % 60;
283                if (this.second < 0)
284                    this.second     += 60;
285                break;
286            case Calendar.MINUTE:
287                this.minute         = (this.minute + amount) % 60;
288                if (this.minute < 0)
289                    this.minute     += 60;
290                break;
291            case Calendar.HOUR:
292                this.hour           = (this.hour + amount) % 24;
293                if (this.hour < 0)
294                    this.hour       += 24;
295                break;
296            case Calendar.DATE: {
297                this.dayOfMonth     = (this.dayOfMonth + amount) % getActualMaximum(Calendar.DATE);
298                if (this.dayOfMonth < 0)
299                    this.dayOfMonth += getActualMaximum(Calendar.DATE);
300                break;
301            }
302            case Calendar.MONTH: {
303                this.month          = (this.month + amount) % 12;
304                if (this.month < 0)
305                    this.month      += 12;
306                if (this.dayOfMonth > getActualMaximum(Calendar.DATE))
307                    this.dayOfMonth = getActualMaximum(Calendar.DATE);
308                break;
309            }
310            case Calendar.YEAR:
311                this.year           += amount;
312                break;
313            }
314            computeTime();
315        }
316    
317    
318        // Compares the time field records.
319        public boolean before(GregorianCalendar when) {
320                return this.date.before(when.getTime());
321        }
322        public boolean after(GregorianCalendar when) {
323                return this.date.after(when.getTime());
324        }
325        public boolean equals(GregorianCalendar obj) {
326            return this.date.equals(obj.getTime());
327        }
328    
329        public boolean isLeapYear() {
330            return isLeapYear(this.year);
331        }
332        public static boolean isLeapYear(int year) {
333            if ((year % 4) == 0    &&    ((year % 100) != 0  ||  (year % 400) == 0))
334                return true;
335            return false;
336        }
337    
338    
339        // Converts the current millisecond time value time to field values in fields[].
340        protected  void computeFields() {
341            this.second             = this.date.getSeconds();
342            this.minute             = this.date.getMinutes();
343            this.hour               = this.date.getHours();
344            if (this.hour < 12) {
345                this.amPm           = Calendar.AM;
346            } else {
347                this.hour           -= 12;
348                this.amPm           = Calendar.PM;
349            }
350            this.dayOfMonth         = this.date.getDate();
351            this.month              = this.date.getMonth();
352            this.year               = this.date.getYear() + 1900;
353           
354        }
355        // Converts the current field values in fields[] to the millisecond time value time.
356        protected   void computeTime() {
357            this.date               = new Date(this.year - 1900, this.month, this.dayOfMonth, this.hour, this.minute, this.second);
358        }
359    
360        // Overrides Cloneable
361        public Object clone() {
362            GregorianCalendar newCal                = new GregorianCalendar();
363            newCal.setTime(this.date);
364            return newCal;
365        }
366    
367    } // end of class GregorianCalendar