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 * https://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 */ 017package org.apache.commons.validator.routines; 018 019import java.text.DateFormat; 020import java.text.Format; 021import java.util.Calendar; 022import java.util.Locale; 023import java.util.TimeZone; 024 025/** 026 * <p><strong>Time Validation</strong> and Conversion routines ({@code java.util.Calendar}).</p> 027 * 028 * <p>This validator provides a number of methods for validating/converting 029 * a {@link String} time value to a {@code java.util.Calendar} using 030 * {@link DateFormat} to parse either:</p> 031 * <ul> 032 * <li>using the default format for the default {@link Locale}</li> 033 * <li>using a specified pattern with the default {@link Locale}</li> 034 * <li>using the default format for a specified {@link Locale}</li> 035 * <li>using a specified pattern with a specified {@link Locale}</li> 036 * </ul> 037 * 038 * <p>For each of the above mechanisms, conversion method (that is, the 039 * {@code validate} methods) implementations are provided which 040 * either use the default {@code TimeZone} or allow the 041 * {@code TimeZone} to be specified.</p> 042 * 043 * <p>Use one of the {@code isValid()} methods to just validate or 044 * one of the {@code validate()} methods to validate and receive a 045 * <em>converted</em> {@link Calendar} value for the time.</p> 046 * 047 * <p>Implementations of the {@code validate()} method are provided 048 * to create {@link Calendar} objects for different <em>time zones</em> 049 * if the system default is not appropriate.</p> 050 * 051 * <p>Alternatively the CalendarValidator's {@code adjustToTimeZone()} method 052 * can be used to adjust the {@code TimeZone} of the {@link Calendar} 053 * object afterwards.</p> 054 * 055 * <p>Once a value has been successfully converted the following 056 * methods can be used to perform various time comparison checks:</p> 057 * <ul> 058 * <li>{@code compareTime()} compares the hours, minutes, seconds 059 * and milliseconds of two calendars, returning 0, -1 or +1 indicating 060 * whether the first time is equal, before or after the second.</li> 061 * <li>{@code compareSeconds()} compares the hours, minutes and 062 * seconds of two times, returning 0, -1 or +1 indicating 063 * whether the first is equal to, before or after the second.</li> 064 * <li>{@code compareMinutes()} compares the hours and minutes 065 * two times, returning 0, -1 or +1 indicating 066 * whether the first is equal to, before or after the second.</li> 067 * <li>{@code compareHours()} compares the hours 068 * of two times, returning 0, -1 or +1 indicating 069 * whether the first is equal to, before or after the second.</li> 070 * </ul> 071 * 072 * <p>So that the same mechanism used for parsing an <em>input</em> value 073 * for validation can be used to format <em>output</em>, corresponding 074 * {@code format()} 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 {@link Locale}</li> 079 * <li>using the format for the <em>default</em> {@link Locale}</li> 080 * </ul> 081 * 082 * @since 1.3.0 083 */ 084public class TimeValidator extends AbstractCalendarValidator { 085 086 private static final long serialVersionUID = 3494007492269691581L; 087 088 private static final TimeValidator VALIDATOR = new TimeValidator(); 089 090 /** 091 * Gets the singleton instance of this validator. 092 * 093 * @return A singleton instance of the TimeValidator. 094 */ 095 public static TimeValidator getInstance() { 096 return VALIDATOR; 097 } 098 099 /** 100 * Constructs a <em>strict</em> instance with <em>short</em> 101 * time style. 102 */ 103 public TimeValidator() { 104 this(true, DateFormat.SHORT); 105 } 106 107 /** 108 * Constructs an instance with the specified <em>strict</em> 109 * and <em>time style</em> parameters. 110 * 111 * @param strict {@code true} if strict 112 * {@code Format} parsing should be used. 113 * @param timeStyle the time style to use for Locale validation. 114 */ 115 public TimeValidator(final boolean strict, final int timeStyle) { 116 super(strict, -1, timeStyle); 117 } 118 119 /** 120 * <p>Compare Hours.</p> 121 * 122 * @param value The {@link Calendar} value to check. 123 * @param compare The {@link Calendar} to compare the value to. 124 * @return Zero if the hours are equal, -1 if first 125 * parameter's hour is less than the seconds and +1 if the first 126 * parameter's hour is greater than. 127 */ 128 public int compareHours(final Calendar value, final Calendar compare) { 129 return compareTime(value, compare, Calendar.HOUR_OF_DAY); 130 } 131 132 /** 133 * <p>Compare Minutes (hours and minutes).</p> 134 * 135 * @param value The {@link Calendar} value to check. 136 * @param compare The {@link Calendar} to compare the value to. 137 * @return Zero if the hours are equal, -1 if first 138 * parameter's minutes are less than the seconds and +1 if the first 139 * parameter's minutes are greater than. 140 */ 141 public int compareMinutes(final Calendar value, final Calendar compare) { 142 return compareTime(value, compare, Calendar.MINUTE); 143 } 144 145 /** 146 * <p>Compare Seconds (hours, minutes and seconds).</p> 147 * 148 * @param value The {@link Calendar} value to check. 149 * @param compare The {@link Calendar} to compare the value to. 150 * @return Zero if the hours are equal, -1 if first 151 * parameter's seconds are less than the seconds and +1 if the first 152 * parameter's seconds are greater than. 153 */ 154 public int compareSeconds(final Calendar value, final Calendar compare) { 155 return compareTime(value, compare, Calendar.SECOND); 156 } 157 158 /** 159 * <p>Compare Times (hour, minute, second and millisecond - not date).</p> 160 * 161 * @param value The {@link Calendar} value to check. 162 * @param compare The {@link Calendar} to compare the value to. 163 * @return Zero if the hours are equal, -1 if first 164 * time is less than the seconds and +1 if the first 165 * time is greater than. 166 */ 167 public int compareTime(final Calendar value, final Calendar compare) { 168 return compareTime(value, compare, Calendar.MILLISECOND); 169 } 170 171 /** 172 * <p>Convert the parsed {@code Date} to a {@link Calendar}.</p> 173 * 174 * @param value The parsed {@code Date} object created. 175 * @param formatter The Format used to parse the value with. 176 * @return The parsed value converted to a {@link Calendar}. 177 */ 178 @Override 179 protected Object processParsedValue(final Object value, final Format formatter) { 180 return ((DateFormat) formatter).getCalendar(); 181 } 182 183 /** 184 * <p>Validate/convert a time using the default {@link Locale} 185 * and {@code TimeZone}. 186 * 187 * @param value The value validation is being performed on. 188 * @return The parsed {@link Calendar} if valid or {@code null} 189 * if invalid. 190 */ 191 public Calendar validate(final String value) { 192 return (Calendar) parse(value, (String) null, (Locale) null, (TimeZone) null); 193 } 194 195 /** 196 * <p>Validate/convert a time using the specified {@link Locale} 197 * default {@code TimeZone}. 198 * 199 * @param value The value validation is being performed on. 200 * @param locale The locale to use for the time format, system default if null. 201 * @return The parsed {@link Calendar} if valid or {@code null} if invalid. 202 */ 203 public Calendar validate(final String value, final Locale locale) { 204 return (Calendar) parse(value, (String) null, locale, (TimeZone) null); 205 } 206 207 /** 208 * <p>Validate/convert a time using the specified {@link Locale} 209 * and {@code TimeZone}. 210 * 211 * @param value The value validation is being performed on. 212 * @param locale The locale to use for the time format, system default if null. 213 * @param timeZone The Time Zone used to parse the time, system default if null. 214 * @return The parsed {@link Calendar} if valid or {@code null} if invalid. 215 */ 216 public Calendar validate(final String value, final Locale locale, final TimeZone timeZone) { 217 return (Calendar) parse(value, (String) null, locale, timeZone); 218 } 219 220 /** 221 * <p>Validate/convert a time using the specified <em>pattern</em> and 222 * default {@code TimeZone}. 223 * 224 * @param value The value validation is being performed on. 225 * @param pattern The pattern used to validate the value against. 226 * @return The parsed {@link Calendar} if valid or {@code null} if invalid. 227 */ 228 public Calendar validate(final String value, final String pattern) { 229 return (Calendar) parse(value, pattern, (Locale) null, (TimeZone) null); 230 } 231 232 /** 233 * <p>Validate/convert a time using the specified pattern and {@link Locale} 234 * and the default {@code TimeZone}. 235 * 236 * @param value The value validation is being performed on. 237 * @param pattern The pattern used to validate the value against, or the 238 * default for the {@link Locale} if {@code null}. 239 * @param locale The locale to use for the date format, system default if null. 240 * @return The parsed {@link Calendar} if valid or {@code null} if invalid. 241 */ 242 public Calendar validate(final String value, final String pattern, final Locale locale) { 243 return (Calendar) parse(value, pattern, locale, (TimeZone) null); 244 } 245 246 /** 247 * <p>Validate/convert a time using the specified pattern, {@link Locale} 248 * and {@code TimeZone}. 249 * 250 * @param value The value validation is being performed on. 251 * @param pattern The pattern used to validate the value against, or the 252 * default for the {@link Locale} if {@code null}. 253 * @param locale The locale to use for the date format, system default if null. 254 * @param timeZone The Time Zone used to parse the date, system default if null. 255 * @return The parsed {@link Calendar} if valid or {@code null} if invalid. 256 */ 257 public Calendar validate(final String value, final String pattern, final Locale locale, final TimeZone timeZone) { 258 return (Calendar) parse(value, pattern, locale, timeZone); 259 } 260 261 /** 262 * <p>Validate/convert a time using the specified <em>pattern</em> 263 * and {@code TimeZone}. 264 * 265 * @param value The value validation is being performed on. 266 * @param pattern The pattern used to validate the value against. 267 * @param timeZone The Time Zone used to parse the time, system default if null. 268 * @return The parsed {@link Calendar} if valid or {@code null} if invalid. 269 */ 270 public Calendar validate(final String value, final String pattern, final TimeZone timeZone) { 271 return (Calendar) parse(value, pattern, (Locale) null, timeZone); 272 } 273 274 /** 275 * <p>Validate/convert a time using the specified {@code TimeZone} 276 * and default {@link Locale}. 277 * 278 * @param value The value validation is being performed on. 279 * @param timeZone The Time Zone used to parse the time, system default if null. 280 * @return The parsed {@link Calendar} if valid or {@code null} if invalid. 281 */ 282 public Calendar validate(final String value, final TimeZone timeZone) { 283 return (Calendar) parse(value, (String) null, (Locale) null, timeZone); 284 } 285}