Source code: com/RuntimeCollective/webapps/bean/DateBean.java
1 /* $Header: /home/CVS/rjp/src/com/RuntimeCollective/webapps/bean/DateBean.java,v 1.19 2003/09/30 15:13:09 joe Exp $
2 * $Revision: 1.19 $
3 * $Date: 2003/09/30 15:13:09 $
4 *
5 * ====================================================================
6 *
7 * Josephine : http://www.runtime-collective.com/josephine/index.html
8 *
9 * Copyright (C) 2003 Runtime Collective
10 *
11 * This product includes software developed by the
12 * Apache Software Foundation (http://www.apache.org/).
13 *
14 * This library is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU Lesser General Public
16 * License as published by the Free Software Foundation; either
17 * version 2.1 of the License, or (at your option) any later version.
18 *
19 * This library is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 * Lesser General Public License for more details.
23 *
24 * You should have received a copy of the GNU Lesser General Public
25 * License along with this library; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 *
28 */
29
30 package com.RuntimeCollective.webapps.bean;
31
32 import java.text.SimpleDateFormat;
33 import java.util.Date;
34 import java.util.GregorianCalendar;
35 import com.RuntimeCollective.webapps.RuntimeParameters;
36
37 /** A date (and optional time) entered by a user (system-generated dates can stick with java.util.Date.). This class wraps a <code>java.util.Date</code> turning it into a bean including convenience methods for setting its day/month/year/hour/second values, validating and displaying.
38 * <p><strong>Note</strong> - a <code>DateBean</code> set using an <code>InputDateTag</code> <i>must</i> be validated (using <code>DateBean.isValid</code>) before the content is transferred to a bean. This method not only validates the date, but also sets the internal <code>java.util.Date</code>.
39 *
40 * @version $Id: DateBean.java,v 1.19 2003/09/30 15:13:09 joe Exp $
41 * @see com.RuntimeCollective.webapps.tag.DateInputTag
42 */
43 public class DateBean extends Date {
44
45 /** The months of the year {"Jan","Feb", etc}. */
46 private static final String[] months = {"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};
47
48 /** The integer values for the date represented by this bean. */
49 private int iYear,iMonth,iDay,iHour,iMinute;
50
51 /** The date-time formatter. */
52 public static final SimpleDateFormat dateTimeFormatter = new SimpleDateFormat("dd-MMM-yyyy HH:mm");
53
54
55 // == Constructor ================================
56
57 /** Default constructor sets the date, day, month, and year to today, and the time to the current time. */
58 public DateBean() {
59 super();
60 setFields();
61 }
62 /** Constructor sets the date, day, month, and year from a Date. If date is null then sets values to today. */
63 public DateBean(Date d) {
64 super();
65 if ( d!=null ) this.setTime( d.getTime() );
66 setFields();
67 //RuntimeParameters.logDebug( this, "New date bean initialised to "+getDayString()+"-"+getMonthString()+"-"+getYearString() );
68 }
69
70 // == Properties ==================================
71
72 /** The day of the month. */
73 protected String day = null;
74 /** Set the day of the month. */
75 public void setDayString( String day ) { this.day = day; }
76 /** Get the day of the month. */
77 public String getDayString() { return this.day; }
78
79 /** The month number (1-12). */
80 protected String month = null;
81 /** Set the month number (1-12). */
82 public void setMonthString( String month ) {
83 this.month = month;
84 }
85 /** Get the month number (1-12). */
86 public String getMonthString() { return this.month; }
87
88 /** The year. */
89 protected String year = null;
90 /** Set the year. */
91 public void setYearString( String year ) { this.year = year; }
92 /** Get the year. */
93 public String getYearString() { return this.year; }
94
95 /** The hour. */
96 protected String hour = "00";
97 /** Set the hour. */
98 public void setHourString( String hour ) { this.hour = hour; }
99 /** Get the hour. */
100 public String getHourString() { return this.hour; }
101
102 /** The minute. */
103 protected String minute = "00";
104 /** Set the minute. */
105 public void setMinuteString( String minute ) { this.minute = minute; }
106 /** Get the minute. */
107 public String getMinuteString() { return this.minute; }
108
109
110 // == Other Methods ==================================
111
112 /** Set the day, month, and year fields from the internal Date object. */
113 public void setFields() {
114 GregorianCalendar cal = new GregorianCalendar();
115 cal.setTime( this );
116 iDay = cal.get(cal.DAY_OF_MONTH);
117 iMonth = cal.get(cal.MONTH) + 1;
118 iYear = cal.get(cal.YEAR);
119 iHour = cal.get(cal.HOUR_OF_DAY);
120 iMinute = cal.get(cal.MINUTE);
121 day = Integer.toString( iDay );
122 month = Integer.toString( iMonth );
123 year = Integer.toString( iYear );
124 hour = Integer.toString( iHour );
125 minute = Integer.toString( iMinute );
126 }
127
128 /** Check whether the date and time fields are valid and represent a valid date in the future/past, and update the date accordingly.
129 * @param past If <code>true</code> then the date must be a valid past date. If <code>false</code> then the date must be a valid future date.
130 * @return <li><code>true</code> - if the day, month, and year are valid. If this is the case then the internal <code>Date</code> will be set to this date.</li>
131 * <li><code>false</code> - if the day,month, and year are not all valid. If this is the case then the internal <code>Date</code> will be unchanged.</li>
132 */
133 public boolean isValid( boolean past ) {
134 // first check if it is a valid date.
135 boolean isValid = isValid();
136 // if valid then check whether it is in the future / past as appropriate
137 if ( isValid ) {
138 Date now = new Date();
139 isValid = ( this.before( now ) == past );
140 }
141 return isValid;
142 }
143
144 /** Check whether the date and time fields are valid and update the date accordingly.
145 * @return <li><code>true</code> - if the day, month, and year are valid. If this is the case then the internal <code>Date</code> will be set to this date.</li>
146 * <li><code>false</code> - if the day,month, and year are not all valid; or the year is not in the range 1800-2200. If this is the case then the internal <code>Date</code> will be unchanged.</li>
147 */
148 public boolean isValid() {
149
150 try {
151 // First check that we have valid integers
152 iDay = Integer.parseInt( day );
153 iMonth = Integer.parseInt( month );
154 iYear = Integer.parseInt( year );
155 iHour = Integer.parseInt( hour );
156 iMinute = Integer.parseInt( minute );
157
158 if ( (iDay<1) || (iDay>31) || (iMonth<1) || (iMonth>12) || (iYear<1800) || (iYear>2200) || (iHour<0) || (iHour>23) || (iMinute<0) || (iMinute>59) )
159 return false;
160
161 // Then try to construct a valid time from those integers.
162 GregorianCalendar cal = new GregorianCalendar();
163 cal.setLenient( false );
164 cal.set(iYear, iMonth-1, iDay, iHour, iMinute);
165 setTime(cal.getTime().getTime());
166 //RuntimeParameters.log(this,"Setting time to "+cal.getTime().getTime());
167 return true;
168
169 } catch (Exception e) {
170 return false;
171 }
172 }
173
174 /** Show this date in the format 'DD-MON-YYYY HH:MM' */
175 public String toString() {
176 setFields();
177 return day +"-"+ months[Integer.parseInt(month)-1] +"-"+ year;
178 }
179
180 /** Show this date in the format 'DD-MON-YYYY'.
181 * NB this method is equivalen to `toString', but uses the getter bean property method convention.
182 */
183 public String getDisplay() {
184 return toString();
185 }
186
187 /** Show this date in the format 'DD-MON-YYYY HH:MM'.
188 * NB this method is equivalen to `toString', but uses the getter bean property method convention.
189 */
190 public String getDateTimeDisplay() {
191 return dateTimeFormatter.format( (Date) this );
192 }
193
194 /** Convert this date bean to a format suitable for insertion into a SQL Date column.
195 * @return "YYYY-MM-DD", or "" if date bean is null.
196 * @deprecated This method seems buggy under Oracle. Instead, just pass the java.util.Date
197 * object straight to RuntimeDataSource.save(...); it will format it correctly.
198 */
199 public static String toSql(DateBean date) {
200 if ( date==null ) return "";
201 date.setFields();
202 return dateTimeFormatter.format( (Date) date );
203 }
204
205 /** Generate a DateBean from an object returned from a JDBC SQL query.
206 */
207 public static DateBean fromSql(Object result) {
208 Date d = (Date) result;
209 return new DateBean( d );
210 }
211
212 /** If this bean represented the date of birth of someone how old would they be in years.
213 * If the date is in the future, then the result will be < 1.
214 * <p> NB this DateBean should be validated using isValid() before calling this method. The results of calling this on an un-validated date are unpredictable. */
215 public int age() {
216 // Today's date
217 DateBean today = new DateBean();
218 // The age in years
219 int age;
220 // Find the number of whole years between the dates
221 age = today.iYear - 1 - this.iYear;
222 // If we are currently later in the year than the person's birthday, then add one
223 if ( (today.iMonth > this.iMonth)
224 || ( (today.iMonth == today.iMonth) && (today.iDay >= today.iDay) ) )
225 age = age + 1;
226 return age;
227 }
228
229 /**
230 * Compares this DateBean with another object for equality.
231 * The result is <code>true</code> if and only if the argument is not <code>null</code>
232 * and is a <code>Date</code> or <code>DateBean</code> object that
233 * represents the same point in time, to the minute, as this object.
234 * Seconds and millis are ignored.
235 * Throws a ClassCastException if the object is not a DateBean nor a Date, says false if the object is null.
236 */
237 public boolean equals(Object obj) {
238 if (obj == null) {
239 return false;
240
241 } else if (obj instanceof DateBean) {
242 DateBean db = (DateBean)obj;
243 return (getYearString().equals(db.getYearString())
244 && getMonthString().equals(db.getMonthString())
245 && getDayString().equals(db.getDayString())
246 && getHourString().equals(db.getHourString())
247 && getMinuteString().equals(db.getMinuteString()));
248
249 } else if (obj instanceof Date) {
250 return equals(new DateBean((Date) obj));
251
252 } else {
253 throw new ClassCastException("DateBean.equals(obj) requires obj to be either a DateBean or a Date, while it is : "+(obj == null ? "null" : obj.getClass().getName()));
254 }
255 }
256
257 /**
258 * Compares the day of this DateBean with another object for equality.
259 * The result is <code>true</code> if and only if the argument is not <code>null</code>
260 * and is a <code>Date</code> or <code>DateBean</code> object that
261 * represents the same point in time, to the day (eg Year, Month, Day), as this object.
262 * Hours, Minutes, Seconds and millis are ignored.
263 */
264 public boolean equalsDay(Object obj) {
265 if (obj instanceof DateBean) {
266 DateBean db = (DateBean)obj;
267 return (getYearString().equals(db.getYearString())
268 && getMonthString().equals(db.getMonthString())
269 && getDayString().equals(db.getDayString()));
270
271 } else if (obj instanceof Date) {
272 return equals(new DateBean((Date) obj));
273
274 } else {
275 throw new ClassCastException("DateBean.equals(obj) requires obj to be either a DateBean or a Date, while it is : "+(obj == null ? "null" : obj.getClass().getName()));
276 }
277 }
278 }
279
280
281