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.Date; 023 import java.util.Locale; 024 import java.util.TimeZone; 025 026 /** 027 * <p><b>Date Validation</b> and Conversion routines (<code>java.util.Date</code>).</p> 028 * 029 * <p>This validator provides a number of methods for validating/converting 030 * a <code>String</code> date value to a <code>java.util.Date</code> using 031 * <code>java.text.DateFormat</code> to parse either:</p> 032 * <ul> 033 * <li>using the default format for the default <code>Locale</code></li> 034 * <li>using a specified pattern with the default <code>Locale</code></li> 035 * <li>using the default format for a specified <code>Locale</code></li> 036 * <li>using a specified pattern with a specified <code>Locale</code></li> 037 * </ul> 038 * 039 * <p>For each of the above mechanisms, conversion method (i.e the 040 * <code>validate</code> methods) implementations are provided which 041 * either use the default <code>TimeZone</code> or allow the 042 * <code>TimeZone</code> to be specified.</p> 043 * 044 * <p>Use one of the <code>isValid()</code> methods to just validate or 045 * one of the <code>validate()</code> methods to validate and receive a 046 * <i>converted</i> <code>Date</code> value.</p> 047 * 048 * <p>Implementations of the <code>validate()</code> method are provided 049 * to create <code>Date</code> objects for different <i>time zones</i> 050 * if the system default is not appropriate.</p> 051 * 052 * <p>Once a value has been sucessfully converted the following 053 * methods can be used to perform various date comparison checks:</p> 054 * <ul> 055 * <li><code>compareDates()</code> compares the day, month and 056 * year of two dates, returing 0, -1 or +1 indicating 057 * whether the first date is equal, before or after the second.</li> 058 * <li><code>compareWeeks()</code> compares the week and 059 * year of two dates, returing 0, -1 or +1 indicating 060 * whether the first week is equal, before or after the second.</li> 061 * <li><code>compareMonths()</code> compares the month and 062 * year of two dates, returing 0, -1 or +1 indicating 063 * whether the first month is equal, before or after the second.</li> 064 * <li><code>compareQuarters()</code> compares the quarter and 065 * year of two dates, returing 0, -1 or +1 indicating 066 * whether the first quarter is equal, before or after the second.</li> 067 * <li><code>compareYears()</code> compares the 068 * year of two dates, returing 0, -1 or +1 indicating 069 * whether the first year is equal, before or after the second.</li> 070 * </ul> 071 * 072 * <p>So that the same mechanism used for parsing an <i>input</i> value 073 * for validation can be used to format <i>output</i>, corresponding 074 * <code>format()</code> methods are also provided. That is you can 075 * format either:</p> 076 * <ul> 077 * <li>using a specified pattern</li> 078 * <li>using the format for a specified <code>Locale</code></li> 079 * <li>using the format for the <i>default</i> <code>Locale</code></li> 080 * </ul> 081 * 082 * @version $Revision: 493905 $ $Date: 2007-01-08 03:11:38 +0100 (Mo, 08. Jan 2007) $ 083 * @since Validator 1.3.0 084 */ 085 public class DateValidator extends AbstractCalendarValidator { 086 087 private static final DateValidator VALIDATOR = new DateValidator(); 088 089 /** 090 * Return a singleton instance of this validator. 091 * @return A singleton instance of the DateValidator. 092 */ 093 public static DateValidator getInstance() { 094 return VALIDATOR; 095 } 096 097 /** 098 * Construct a <i>strict</i> instance with <i>short</i> 099 * 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 }