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