1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.apache.commons.validator.routines;
22
23 import java.text.DateFormat;
24 import java.text.Format;
25 import java.util.Calendar;
26 import java.util.Date;
27 import java.util.Locale;
28 import java.util.TimeZone;
29
30 /***
31 * <p><b>Date Validation</b> and Conversion routines (<code>java.util.Date</code>).</p>
32 *
33 * <p>This validator provides a number of methods for validating/converting
34 * a <code>String</code> date value to a <code>java.util.Date</code> using
35 * <code>java.text.DateFormat</code> to parse either:</p>
36 * <ul>
37 * <li>using the default format for the default <code>Locale</code></li>
38 * <li>using a specified pattern with the default <code>Locale</code></li>
39 * <li>using the default format for a specified <code>Locale</code></li>
40 * <li>using a specified pattern with a specified <code>Locale</code></li>
41 * </ul>
42 *
43 * <p>For each of the above mechanisms, conversion method (i.e the
44 * <code>validate</code> methods) implementations are provided which
45 * either use the default <code>TimeZone</code> or allow the
46 * <code>TimeZone</code> to be specified.</p>
47 *
48 * <p>Use one of the <code>isValid()</code> methods to just validate or
49 * one of the <code>validate()</code> methods to validate and receive a
50 * <i>converted</i> <code>Date</code> value.</p>
51 *
52 * <p>Implementations of the <code>validate()</code> method are provided
53 * to create <code>Date</code> objects for different <i>time zones</i>
54 * if the system default is not appropriate.</p>
55 *
56 * <p>Once a value has been sucessfully converted the following
57 * methods can be used to perform various date comparison checks:</p>
58 * <ul>
59 * <li><code>compareDates()</code> compares the day, month and
60 * year of two dates, returing 0, -1 or +1 indicating
61 * whether the first date is equal, before or after the second.</li>
62 * <li><code>compareWeeks()</code> compares the week and
63 * year of two dates, returing 0, -1 or +1 indicating
64 * whether the first week is equal, before or after the second.</li>
65 * <li><code>compareMonths()</code> compares the month and
66 * year of two dates, returing 0, -1 or +1 indicating
67 * whether the first month is equal, before or after the second.</li>
68 * <li><code>compareQuarters()</code> compares the quarter and
69 * year of two dates, returing 0, -1 or +1 indicating
70 * whether the first quarter is equal, before or after the second.</li>
71 * <li><code>compareYears()</code> compares the
72 * year of two dates, returing 0, -1 or +1 indicating
73 * whether the first year is equal, before or after the second.</li>
74 * </ul>
75 *
76 * <p>So that the same mechanism used for parsing an <i>input</i> value
77 * for validation can be used to format <i>output</i>, corresponding
78 * <code>format()</code> methods are also provided. That is you can
79 * format either:</p>
80 * <ul>
81 * <li>using a specified pattern</li>
82 * <li>using the format for a specified <code>Locale</code></li>
83 * <li>using the format for the <i>default</i> <code>Locale</code></li>
84 * </ul>
85 *
86 * @version $Revision: 386637 $ $Date: 2006-03-17 13:22:26 +0000 (Fri, 17 Mar 2006) $
87 * @since Validator 1.3.0
88 */
89 public class DateValidator extends AbstractCalendarValidator {
90
91 private static final DateValidator VALIDATOR = new DateValidator();
92
93 /***
94 * Return a singleton instance of this validator.
95 * @return A singleton instance of the DateValidator.
96 */
97 public static DateValidator getInstance() {
98 return VALIDATOR;
99 }
100
101 /***
102 * Construct a <i>strict</i> instance with <i>short</i>
103 * date style.
104 */
105 public DateValidator() {
106 this(true, DateFormat.SHORT);
107 }
108
109 /***
110 * Construct an instance with the specified <i>strict</i>
111 * and <i>date style</i> parameters.
112 *
113 * @param strict <code>true</code> if strict
114 * <code>Format</code> parsing should be used.
115 * @param dateStyle the date style to use for Locale validation.
116 */
117 public DateValidator(boolean strict, int dateStyle) {
118 super(strict, dateStyle, -1);
119 }
120
121 /***
122 * <p>Validate/convert a <code>Date</code> using the default
123 * <code>Locale</code> and <code>TimeZone</code>.
124 *
125 * @param value The value validation is being performed on.
126 * @return The parsed <code>Date</code> if valid or <code>null</code>
127 * if invalid.
128 */
129 public Date validate(String value) {
130 return (Date)parse(value, (String)null, (Locale)null, (TimeZone)null);
131 }
132
133 /***
134 * <p>Validate/convert a <code>Date</code> using the specified
135 * <code>TimeZone</code> and default <code>Locale</code>.
136 *
137 * @param value The value validation is being performed on.
138 * @param timeZone The Time Zone used to parse the date, system default if null.
139 * @return The parsed <code>Date</code> if valid or <code>null</code> if invalid.
140 */
141 public Date validate(String value, TimeZone timeZone) {
142 return (Date)parse(value, (String)null, (Locale)null, timeZone);
143 }
144
145 /***
146 * <p>Validate/convert a <code>Date</code> using the specified
147 * <i>pattern</i> and default <code>TimeZone</code>.
148 *
149 * @param value The value validation is being performed on.
150 * @param pattern The pattern used to validate the value against, or the
151 * default for the <code>Locale</code> if <code>null</code>.
152 * @return The parsed <code>Date</code> if valid or <code>null</code> if invalid.
153 */
154 public Date validate(String value, String pattern) {
155 return (Date)parse(value, pattern, (Locale)null, (TimeZone)null);
156 }
157
158 /***
159 * <p>Validate/convert a <code>Date</code> using the specified
160 * <i>pattern</i> and <code>TimeZone</code>.
161 *
162 * @param value The value validation is being performed on.
163 * @param pattern The pattern used to validate the value against, or the
164 * default for the <code>Locale</code> if <code>null</code>.
165 * @param timeZone The Time Zone used to parse the date, system default if null.
166 * @return The parsed <code>Date</code> if valid or <code>null</code> if invalid.
167 */
168 public Date validate(String value, String pattern, TimeZone timeZone) {
169 return (Date)parse(value, pattern, (Locale)null, timeZone);
170 }
171
172 /***
173 * <p>Validate/convert a <code>Date</code> using the specified
174 * <code>Locale</code> and default <code>TimeZone</code>.
175 *
176 * @param value The value validation is being performed on.
177 * @param locale The locale to use for the date format, system default if null.
178 * @return The parsed <code>Date</code> if valid or <code>null</code> if invalid.
179 */
180 public Date validate(String value, Locale locale) {
181 return (Date)parse(value, (String)null, locale, (TimeZone)null);
182 }
183
184 /***
185 * <p>Validate/convert a <code>Date</code> using the specified
186 * <code>Locale</code> and <code>TimeZone</code>.
187 *
188 * @param value The value validation is being performed on.
189 * @param locale The locale to use for the date format, system default if null.
190 * @param timeZone The Time Zone used to parse the date, system default if null.
191 * @return The parsed <code>Date</code> if valid or <code>null</code> if invalid.
192 */
193 public Date validate(String value, Locale locale, TimeZone timeZone) {
194 return (Date)parse(value, (String)null, locale, timeZone);
195 }
196
197 /***
198 * <p>Validate/convert a <code>Date</code> using the specified pattern
199 * and <code>Locale</code> and the default <code>TimeZone</code>.
200 *
201 * @param value The value validation is being performed on.
202 * @param pattern The pattern used to validate the value against, or the
203 * default for the <code>Locale</code> if <code>null</code>.
204 * @param locale The locale to use for the date format, system default if null.
205 * @return The parsed <code>Date</code> if valid or <code>null</code> if invalid.
206 */
207 public Date validate(String value, String pattern, Locale locale) {
208 return (Date)parse(value, pattern, locale, (TimeZone)null);
209 }
210
211 /***
212 * <p>Validate/convert a <code>Date</code> using the specified
213 * pattern, and <code>Locale</code> and <code>TimeZone</code>.
214 *
215 * @param value The value validation is being performed on.
216 * @param pattern The pattern used to validate the value against, or the
217 * default for the <code>Locale</code> if <code>null</code>.
218 * @param locale The locale to use for the date format, system default if null.
219 * @param timeZone The Time Zone used to parse the date, system default if null.
220 * @return The parsed <code>Date</code> if valid or <code>null</code> if invalid.
221 */
222 public Date validate(String value, String pattern, Locale locale, TimeZone timeZone) {
223 return (Date)parse(value, pattern, locale, timeZone);
224 }
225
226 /***
227 * <p>Compare Dates (day, month and year - not time).</p>
228 *
229 * @param value The <code>Calendar</code> value to check.
230 * @param compare The <code>Calendar</code> to compare the value to.
231 * @param timeZone The Time Zone used to compare the dates, system default if null.
232 * @return Zero if the dates are equal, -1 if first
233 * date is less than the seconds and +1 if the first
234 * date is greater than.
235 */
236 public int compareDates(Date value, Date compare, TimeZone timeZone) {
237 Calendar calendarValue = getCalendar(value, timeZone);
238 Calendar calendarCompare = getCalendar(compare, timeZone);
239 return compare(calendarValue, calendarCompare, Calendar.DATE);
240 }
241
242 /***
243 * <p>Compare Weeks (week and year).</p>
244 *
245 * @param value The <code>Date</code> value to check.
246 * @param compare The <code>Date</code> to compare the value to.
247 * @param timeZone The Time Zone used to compare the dates, system default if null.
248 * @return Zero if the weeks are equal, -1 if first
249 * parameter's week is less than the seconds and +1 if the first
250 * parameter's week is greater than.
251 */
252 public int compareWeeks(Date value, Date compare, TimeZone timeZone) {
253 Calendar calendarValue = getCalendar(value, timeZone);
254 Calendar calendarCompare = getCalendar(compare, timeZone);
255 return compare(calendarValue, calendarCompare, Calendar.WEEK_OF_YEAR);
256 }
257
258 /***
259 * <p>Compare Months (month and year).</p>
260 *
261 * @param value The <code>Date</code> value to check.
262 * @param compare The <code>Date</code> to compare the value to.
263 * @param timeZone The Time Zone used to compare the dates, system default if null.
264 * @return Zero if the months are equal, -1 if first
265 * parameter's month is less than the seconds and +1 if the first
266 * parameter's month is greater than.
267 */
268 public int compareMonths(Date value, Date compare, TimeZone timeZone) {
269 Calendar calendarValue = getCalendar(value, timeZone);
270 Calendar calendarCompare = getCalendar(compare, timeZone);
271 return compare(calendarValue, calendarCompare, Calendar.MONTH);
272 }
273
274 /***
275 * <p>Compare Quarters (quarter and year).</p>
276 *
277 * @param value The <code>Date</code> value to check.
278 * @param compare The <code>Date</code> to compare the value to.
279 * @param timeZone The Time Zone used to compare the dates, system default if null.
280 * @return Zero if the months are equal, -1 if first
281 * parameter's quarter is less than the seconds and +1 if the first
282 * parameter's quarter is greater than.
283 */
284 public int compareQuarters(Date value, Date compare, TimeZone timeZone) {
285 return compareQuarters(value, compare, timeZone, 1);
286 }
287
288 /***
289 * <p>Compare Quarters (quarter and year).</p>
290 *
291 * @param value The <code>Date</code> value to check.
292 * @param compare The <code>Date</code> to compare the value to.
293 * @param timeZone The Time Zone used to compare the dates, system default if null.
294 * @param monthOfFirstQuarter The month that the first quarter starts.
295 * @return Zero if the quarters are equal, -1 if first
296 * parameter's quarter is less than the seconds and +1 if the first
297 * parameter's quarter is greater than.
298 */
299 public int compareQuarters(Date value, Date compare, TimeZone timeZone, int monthOfFirstQuarter) {
300 Calendar calendarValue = getCalendar(value, timeZone);
301 Calendar calendarCompare = getCalendar(compare, timeZone);
302 return super.compareQuarters(calendarValue, calendarCompare, monthOfFirstQuarter);
303 }
304
305 /***
306 * <p>Compare Years.</p>
307 *
308 * @param value The <code>Date</code> value to check.
309 * @param compare The <code>Date</code> to compare the value to.
310 * @param timeZone The Time Zone used to compare the dates, system default if null.
311 * @return Zero if the years are equal, -1 if first
312 * parameter's year is less than the seconds and +1 if the first
313 * parameter's year is greater than.
314 */
315 public int compareYears(Date value, Date compare, TimeZone timeZone) {
316 Calendar calendarValue = getCalendar(value, timeZone);
317 Calendar calendarCompare = getCalendar(compare, timeZone);
318 return compare(calendarValue, calendarCompare, Calendar.YEAR);
319 }
320
321 /***
322 * <p>Returns the parsed <code>Date</code> unchanged.</p>
323 *
324 * @param value The parsed <code>Date</code> object created.
325 * @param formatter The Format used to parse the value with.
326 * @return The parsed value converted to a <code>Calendar</code>.
327 */
328 protected Object processParsedValue(Object value, Format formatter) {
329 return value;
330 }
331
332 /***
333 * <p>Convert a <code>Date</code> to a <code>Calendar</code>.</p>
334 *
335 * @param value The date value to be converted.
336 * @return The converted <code>Calendar</code>.
337 */
338 private Calendar getCalendar(Date value, TimeZone timeZone) {
339
340 Calendar calendar = null;
341 if (timeZone != null) {
342 calendar = Calendar.getInstance(timeZone);
343 } else {
344 calendar = Calendar.getInstance();
345 }
346 calendar.setTime(value);
347 return calendar;
348
349 }
350
351 }