001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 package org.apache.commons.validator.routines; 018 019 import java.text.DateFormat; 020 import java.text.Format; 021 import java.util.Calendar; 022 import java.util.Locale; 023 import java.util.TimeZone; 024 025 /** 026 * <p><b>Calendar Validation</b> and Conversion routines (<code>java.util.Calendar</code>).</p> 027 * 028 * <p>This validator provides a number of methods for validating/converting 029 * a <code>String</code> date value to a <code>java.util.Calendar</code> using 030 * <code>java.text.DateFormat</code> to parse either:</p> 031 * <ul> 032 * <li>using the default format for the default <code>Locale</code></li> 033 * <li>using a specified pattern with the default <code>Locale</code></li> 034 * <li>using the default format for a specified <code>Locale</code></li> 035 * <li>using a specified pattern with a specified <code>Locale</code></li> 036 * </ul> 037 * 038 * <p>For each of the above mechanisms, conversion method (i.e the 039 * <code>validate</code> methods) implementations are provided which 040 * either use the default <code>TimeZone</code> or allow the 041 * <code>TimeZone</code> to be specified.</p> 042 * 043 * <p>Use one of the <code>isValid()</code> methods to just validate or 044 * one of the <code>validate()</code> methods to validate and receive a 045 * <i>converted</i> <code>Calendar</code> value.</p> 046 * 047 * <p>Implementations of the <code>validate()</code> method are provided 048 * to create <code>Calendar</code> objects for different <i>time zones</i> 049 * if the system default is not appropriate.</p> 050 * 051 * <p>Alternatively the CalendarValidator's <code>adjustToTimeZone()</code> method 052 * can be used to adjust the <code>TimeZone</code> of the <code>Calendar</code> 053 * object afterwards.</p> 054 * 055 * <p>Once a value has been sucessfully converted the following 056 * methods can be used to perform various date comparison checks:</p> 057 * <ul> 058 * <li><code>compareDates()</code> compares the day, month and 059 * year of two calendars, returing 0, -1 or +1 indicating 060 * whether the first date is equal, before or after the second.</li> 061 * <li><code>compareWeeks()</code> compares the week and 062 * year of two calendars, returing 0, -1 or +1 indicating 063 * whether the first week is equal, before or after the second.</li> 064 * <li><code>compareMonths()</code> compares the month and 065 * year of two calendars, returing 0, -1 or +1 indicating 066 * whether the first month is equal, before or after the second.</li> 067 * <li><code>compareQuarters()</code> compares the quarter and 068 * year of two calendars, returing 0, -1 or +1 indicating 069 * whether the first quarter is equal, before or after the second.</li> 070 * <li><code>compareYears()</code> compares the 071 * year of two calendars, returing 0, -1 or +1 indicating 072 * whether the first year is equal, before or after the second.</li> 073 * </ul> 074 * 075 * <p>So that the same mechanism used for parsing an <i>input</i> value 076 * for validation can be used to format <i>output</i>, corresponding 077 * <code>format()</code> methods are also provided. That is you can 078 * format either:</p> 079 * <ul> 080 * <li>using a specified pattern</li> 081 * <li>using the format for a specified <code>Locale</code></li> 082 * <li>using the format for the <i>default</i> <code>Locale</code></li> 083 * </ul> 084 * 085 * @version $Revision: 493905 $ $Date: 2007-01-08 03:11:38 +0100 (Mo, 08. Jan 2007) $ 086 * @since Validator 1.3.0 087 */ 088 public class CalendarValidator extends AbstractCalendarValidator { 089 090 private static final CalendarValidator VALIDATOR = new CalendarValidator(); 091 092 /** 093 * Return a singleton instance of this validator. 094 * @return A singleton instance of the CalendarValidator. 095 */ 096 public static CalendarValidator getInstance() { 097 return VALIDATOR; 098 } 099 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 }