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 * https://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><strong>Time Validation</strong> and Conversion routines ({@code java.util.Calendar}).</p>
27 *
28 * <p>This validator provides a number of methods for validating/converting
29 * a {@link String} time value to a {@code java.util.Calendar} using
30 * {@link DateFormat} to parse either:</p>
31 * <ul>
32 * <li>using the default format for the default {@link Locale}</li>
33 * <li>using a specified pattern with the default {@link Locale}</li>
34 * <li>using the default format for a specified {@link Locale}</li>
35 * <li>using a specified pattern with a specified {@link Locale}</li>
36 * </ul>
37 *
38 * <p>For each of the above mechanisms, conversion method (that is, the
39 * {@code validate} methods) implementations are provided which
40 * either use the default {@code TimeZone} or allow the
41 * {@code TimeZone} to be specified.</p>
42 *
43 * <p>Use one of the {@code isValid()} methods to just validate or
44 * one of the {@code validate()} methods to validate and receive a
45 * <em>converted</em> {@link Calendar} value for the time.</p>
46 *
47 * <p>Implementations of the {@code validate()} method are provided
48 * to create {@link Calendar} objects for different <em>time zones</em>
49 * if the system default is not appropriate.</p>
50 *
51 * <p>Alternatively the CalendarValidator's {@code adjustToTimeZone()} method
52 * can be used to adjust the {@code TimeZone} of the {@link Calendar}
53 * object afterwards.</p>
54 *
55 * <p>Once a value has been successfully converted the following
56 * methods can be used to perform various time comparison checks:</p>
57 * <ul>
58 * <li>{@code compareTime()} compares the hours, minutes, seconds
59 * and milliseconds of two calendars, returning 0, -1 or +1 indicating
60 * whether the first time is equal, before or after the second.</li>
61 * <li>{@code compareSeconds()} compares the hours, minutes and
62 * seconds of two times, returning 0, -1 or +1 indicating
63 * whether the first is equal to, before or after the second.</li>
64 * <li>{@code compareMinutes()} compares the hours and minutes
65 * two times, returning 0, -1 or +1 indicating
66 * whether the first is equal to, before or after the second.</li>
67 * <li>{@code compareHours()} compares the hours
68 * of two times, returning 0, -1 or +1 indicating
69 * whether the first is equal to, before or after the second.</li>
70 * </ul>
71 *
72 * <p>So that the same mechanism used for parsing an <em>input</em> value
73 * for validation can be used to format <em>output</em>, corresponding
74 * {@code format()} 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 {@link Locale}</li>
79 * <li>using the format for the <em>default</em> {@link Locale}</li>
80 * </ul>
81 *
82 * @since 1.3.0
83 */
84 public class TimeValidator extends AbstractCalendarValidator {
85
86 private static final long serialVersionUID = 3494007492269691581L;
87
88 private static final TimeValidator VALIDATOR = new TimeValidator();
89
90 /**
91 * Gets the singleton instance of this validator.
92 * @return A singleton instance of the TimeValidator.
93 */
94 public static TimeValidator getInstance() {
95 return VALIDATOR;
96 }
97
98 /**
99 * Constructs a <em>strict</em> instance with <em>short</em>
100 * time style.
101 */
102 public TimeValidator() {
103 this(true, DateFormat.SHORT);
104 }
105
106 /**
107 * Constructs an instance with the specified <em>strict</em>
108 * and <em>time style</em> parameters.
109 *
110 * @param strict {@code true} if strict
111 * {@code Format} parsing should be used.
112 * @param timeStyle the time style to use for Locale validation.
113 */
114 public TimeValidator(final boolean strict, final int timeStyle) {
115 super(strict, -1, timeStyle);
116 }
117
118 /**
119 * <p>Compare Hours.</p>
120 *
121 * @param value The {@link Calendar} value to check.
122 * @param compare The {@link Calendar} to compare the value to.
123 * @return Zero if the hours are equal, -1 if first
124 * parameter's hour is less than the seconds and +1 if the first
125 * parameter's hour is greater than.
126 */
127 public int compareHours(final Calendar value, final Calendar compare) {
128 return compareTime(value, compare, Calendar.HOUR_OF_DAY);
129 }
130
131 /**
132 * <p>Compare Minutes (hours and minutes).</p>
133 *
134 * @param value The {@link Calendar} value to check.
135 * @param compare The {@link Calendar} to compare the value to.
136 * @return Zero if the hours are equal, -1 if first
137 * parameter's minutes are less than the seconds and +1 if the first
138 * parameter's minutes are greater than.
139 */
140 public int compareMinutes(final Calendar value, final Calendar compare) {
141 return compareTime(value, compare, Calendar.MINUTE);
142 }
143
144 /**
145 * <p>Compare Seconds (hours, minutes and seconds).</p>
146 *
147 * @param value The {@link Calendar} value to check.
148 * @param compare The {@link Calendar} to compare the value to.
149 * @return Zero if the hours are equal, -1 if first
150 * parameter's seconds are less than the seconds and +1 if the first
151 * parameter's seconds are greater than.
152 */
153 public int compareSeconds(final Calendar value, final Calendar compare) {
154 return compareTime(value, compare, Calendar.SECOND);
155 }
156
157 /**
158 * <p>Compare Times (hour, minute, second and millisecond - not date).</p>
159 *
160 * @param value The {@link Calendar} value to check.
161 * @param compare The {@link Calendar} to compare the value to.
162 * @return Zero if the hours are equal, -1 if first
163 * time is less than the seconds and +1 if the first
164 * time is greater than.
165 */
166 public int compareTime(final Calendar value, final Calendar compare) {
167 return compareTime(value, compare, Calendar.MILLISECOND);
168 }
169
170 /**
171 * <p>Convert the parsed {@code Date} to a {@link Calendar}.</p>
172 *
173 * @param value The parsed {@code Date} object created.
174 * @param formatter The Format used to parse the value with.
175 * @return The parsed value converted to a {@link Calendar}.
176 */
177 @Override
178 protected Object processParsedValue(final Object value, final Format formatter) {
179 return ((DateFormat) formatter).getCalendar();
180 }
181
182 /**
183 * <p>Validate/convert a time using the default {@link Locale}
184 * and {@code TimeZone}.
185 *
186 * @param value The value validation is being performed on.
187 * @return The parsed {@link Calendar} if valid or {@code null}
188 * if invalid.
189 */
190 public Calendar validate(final String value) {
191 return (Calendar) parse(value, (String) null, (Locale) null, (TimeZone) null);
192 }
193
194 /**
195 * <p>Validate/convert a time using the specified {@link Locale}
196 * default {@code TimeZone}.
197 *
198 * @param value The value validation is being performed on.
199 * @param locale The locale to use for the time format, system default if null.
200 * @return The parsed {@link Calendar} if valid or {@code null} if invalid.
201 */
202 public Calendar validate(final String value, final Locale locale) {
203 return (Calendar) parse(value, (String) null, locale, (TimeZone) null);
204 }
205
206 /**
207 * <p>Validate/convert a time using the specified {@link Locale}
208 * and {@code TimeZone}.
209 *
210 * @param value The value validation is being performed on.
211 * @param locale The locale to use for the time format, system default if null.
212 * @param timeZone The Time Zone used to parse the time, system default if null.
213 * @return The parsed {@link Calendar} if valid or {@code null} if invalid.
214 */
215 public Calendar validate(final String value, final Locale locale, final TimeZone timeZone) {
216 return (Calendar) parse(value, (String) null, locale, timeZone);
217 }
218
219 /**
220 * <p>Validate/convert a time using the specified <em>pattern</em> and
221 * default {@code TimeZone}.
222 *
223 * @param value The value validation is being performed on.
224 * @param pattern The pattern used to validate the value against.
225 * @return The parsed {@link Calendar} if valid or {@code null} if invalid.
226 */
227 public Calendar validate(final String value, final String pattern) {
228 return (Calendar) parse(value, pattern, (Locale) null, (TimeZone) null);
229 }
230
231 /**
232 * <p>Validate/convert a time using the specified pattern and {@link Locale}
233 * and the default {@code TimeZone}.
234 *
235 * @param value The value validation is being performed on.
236 * @param pattern The pattern used to validate the value against, or the
237 * default for the {@link Locale} if {@code null}.
238 * @param locale The locale to use for the date format, system default if null.
239 * @return The parsed {@link Calendar} if valid or {@code null} if invalid.
240 */
241 public Calendar validate(final String value, final String pattern, final Locale locale) {
242 return (Calendar) parse(value, pattern, locale, (TimeZone) null);
243 }
244
245 /**
246 * <p>Validate/convert a time using the specified pattern, {@link Locale}
247 * and {@code TimeZone}.
248 *
249 * @param value The value validation is being performed on.
250 * @param pattern The pattern used to validate the value against, or the
251 * default for the {@link Locale} if {@code null}.
252 * @param locale The locale to use for the date format, system default if null.
253 * @param timeZone The Time Zone used to parse the date, system default if null.
254 * @return The parsed {@link Calendar} if valid or {@code null} if invalid.
255 */
256 public Calendar validate(final String value, final String pattern, final Locale locale, final TimeZone timeZone) {
257 return (Calendar) parse(value, pattern, locale, timeZone);
258 }
259
260 /**
261 * <p>Validate/convert a time using the specified <em>pattern</em>
262 * and {@code TimeZone}.
263 *
264 * @param value The value validation is being performed on.
265 * @param pattern The pattern used to validate the value against.
266 * @param timeZone The Time Zone used to parse the time, system default if null.
267 * @return The parsed {@link Calendar} if valid or {@code null} if invalid.
268 */
269 public Calendar validate(final String value, final String pattern, final TimeZone timeZone) {
270 return (Calendar) parse(value, pattern, (Locale) null, timeZone);
271 }
272
273 /**
274 * <p>Validate/convert a time using the specified {@code TimeZone}
275 * and default {@link Locale}.
276 *
277 * @param value The value validation is being performed on.
278 * @param timeZone The Time Zone used to parse the time, system default if null.
279 * @return The parsed {@link Calendar} if valid or {@code null} if invalid.
280 */
281 public Calendar validate(final String value, final TimeZone timeZone) {
282 return (Calendar) parse(value, (String) null, (Locale) null, timeZone);
283 }
284 }