View Javadoc

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