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    *      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 static org.junit.jupiter.api.Assertions.assertEquals;
20  import static org.junit.jupiter.api.Assertions.assertFalse;
21  import static org.junit.jupiter.api.Assertions.assertNotNull;
22  import static org.junit.jupiter.api.Assertions.assertNull;
23  import static org.junit.jupiter.api.Assertions.assertTrue;
24  
25  import java.text.DateFormat;
26  import java.text.SimpleDateFormat;
27  import java.util.Calendar;
28  import java.util.Date;
29  import java.util.Locale;
30  import java.util.TimeZone;
31  
32  import org.apache.commons.lang3.time.TimeZones;
33  import org.apache.commons.validator.util.TestTimeZones;
34  import org.junit.jupiter.api.AfterEach;
35  import org.junit.jupiter.api.BeforeEach;
36  import org.junit.jupiter.api.Test;
37  import org.junitpioneer.jupiter.DefaultLocale;
38  import org.junitpioneer.jupiter.DefaultTimeZone;
39  
40  /**
41   * Test Case for TimeValidator.
42   */
43  class TimeValidatorTest {
44  
45      /**
46       * Create a date instance for a specified time zone, date and time.
47       *
48       * @param zone        The time zone
49       * @param time        the time in HH:mm:ss format
50       * @param millisecond the milliseconds
51       * @return the new Date instance.
52       */
53      protected static Date createDate(final TimeZone zone, final int time, final int millisecond) {
54          final Calendar calendar = createTime(zone, time, millisecond);
55          return calendar.getTime();
56      }
57  
58      /**
59       * Create a calendar instance for a specified time zone, date and time.
60       *
61       * @param zone        The time zone
62       * @param time        the time in HH:mm:ss format
63       * @param millisecond the milliseconds
64       * @return the new Calendar instance.
65       */
66      protected static Calendar createTime(final TimeZone zone, final int time, final int millisecond) {
67          final Calendar calendar = zone == null ? Calendar.getInstance() : Calendar.getInstance(zone);
68          final int hour = time / 10000 * 10000;
69          final int min = time / 100 * 100 - hour;
70          final int sec = time - (hour + min);
71          calendar.set(Calendar.YEAR, 1970);
72          calendar.set(Calendar.MONTH, 0);
73          calendar.set(Calendar.DATE, 1);
74          calendar.set(Calendar.HOUR_OF_DAY, hour / 10000);
75          calendar.set(Calendar.MINUTE, min / 100);
76          calendar.set(Calendar.SECOND, sec);
77          calendar.set(Calendar.MILLISECOND, millisecond);
78          return calendar;
79      }
80  
81      protected TimeValidator validator;
82      protected String[] patternValid = { "23-59-59", "00-00-00", "00-00-01", "0-0-0", "1-12-1", "10-49-18", "16-23-46" };
83      protected Date[] patternExpect = { createDate(null, 235959, 0), createDate(null, 0, 0), createDate(null, 1, 0), createDate(null, 0, 0),
84              createDate(null, 11201, 0), createDate(null, 104918, 0), createDate(null, 162346, 0) };
85      protected String[] localeValid = { "23:59", "00:00", "00:01", "0:0", "1:12", "10:49", "16:23" };
86      protected Date[] localeExpect = { createDate(null, 235900, 0), createDate(null, 0, 0), createDate(null, 100, 0), createDate(null, 0, 0),
87              createDate(null, 11200, 0), createDate(null, 104900, 0), createDate(null, 162300, 0) };
88  
89      protected String[] patternInvalid = { "24-00-00" // midnight
90              , "24-00-01" // past midnight
91              , "25-02-03" // invalid hour
92              , "10-61-31" // invalid minute
93              , "10-01-61" // invalid second
94              , "05:02-29" // invalid sep
95              , "0X-01:01" // invalid sep
96              , "05-0X-01" // invalid char
97              , "10-01-0X" // invalid char
98              , "01:01:05" // invalid pattern
99              , "10-10" // invalid pattern
100             , "10--10" // invalid pattern
101             , "10-10-" }; // invalid pattern
102     protected String[] localeInvalid = { "24:00" // midnight
103             , "24:00" // past midnight
104             , "25:02" // invalid hour
105             , "10:61" // invalid minute
106             , "05-02" // invalid sep
107             , "0X:01" // invalid sep
108             , "05:0X" // invalid char
109             , "01-01" // invalid pattern
110             , "10:" // invalid pattern
111             , "10::1" // invalid pattern
112             , "10:1:" }; // invalid pattern
113 
114     @BeforeEach
115     protected void setUp() {
116         validator = new TimeValidator();
117     }
118 
119     /**
120      * Tear down
121      */
122     @AfterEach
123     protected void tearDown() {
124         validator = null;
125     }
126 
127     /**
128      * Test compare date methods
129      */
130     @Test
131     void testCompare() {
132         final int testTime = 154523;
133         final int min = 100;
134         final int hour = 10000;
135 
136         final Calendar milliGreater = createTime(TimeZones.GMT, testTime, 500); // > milli sec
137         final Calendar value = createTime(TimeZones.GMT, testTime, 400); // test value
138         final Calendar milliLess = createTime(TimeZones.GMT, testTime, 300); // < milli sec
139 
140         final Calendar secGreater = createTime(TimeZones.GMT, testTime + 1, 100); // +1 sec
141         final Calendar secLess = createTime(TimeZones.GMT, testTime - 1, 100); // -1 sec
142 
143         final Calendar minGreater = createTime(TimeZones.GMT, testTime + min, 100); // +1 min
144         final Calendar minLess = createTime(TimeZones.GMT, testTime - min, 100); // -1 min
145 
146         final Calendar hourGreater = createTime(TimeZones.GMT, testTime + hour, 100); // +1 hour
147         final Calendar hourLess = createTime(TimeZones.GMT, testTime - hour, 100); // -1 hour
148 
149         assertEquals(-1, validator.compareTime(value, milliGreater), "milli LT"); // > milli
150         assertEquals(0, validator.compareTime(value, value), "milli EQ"); // same time
151         assertEquals(1, validator.compareTime(value, milliLess), "milli GT"); // < milli
152 
153         assertEquals(-1, validator.compareSeconds(value, secGreater), "secs LT"); // +1 sec
154         assertEquals(0, validator.compareSeconds(value, milliGreater), "secs =1"); // > milli
155         assertEquals(0, validator.compareSeconds(value, value), "secs =2"); // same time
156         assertEquals(0, validator.compareSeconds(value, milliLess), "secs =3"); // < milli
157         assertEquals(1, validator.compareSeconds(value, secLess), "secs GT"); // -1 sec
158 
159         assertEquals(-1, validator.compareMinutes(value, minGreater), "mins LT"); // +1 min
160         assertEquals(0, validator.compareMinutes(value, secGreater), "mins =1"); // +1 sec
161         assertEquals(0, validator.compareMinutes(value, value), "mins =2"); // same time
162         assertEquals(0, validator.compareMinutes(value, secLess), "mins =3"); // -1 sec
163         assertEquals(1, validator.compareMinutes(value, minLess), "mins GT"); // -1 min
164 
165         assertEquals(-1, validator.compareHours(value, hourGreater), "hour LT"); // +1 hour
166         assertEquals(0, validator.compareHours(value, minGreater), "hour =1"); // +1 min
167         assertEquals(0, validator.compareHours(value, value), "hour =2"); // same time
168         assertEquals(0, validator.compareHours(value, minLess), "hour =3"); // -1 min
169         assertEquals(1, validator.compareHours(value, hourLess), "hour GT"); // -1 hour
170 
171     }
172 
173     /**
174      * Test Invalid Dates with "locale" validation
175      */
176     @Test
177     @DefaultLocale("en-GB")
178     void testFormat() {
179         // The JVM format varies; calculate expected results
180         final Calendar cal = createTime(null, 164923, 0);
181         final DateFormat df = DateFormat.getTimeInstance(DateFormat.SHORT);
182         final String val = df.format(cal.getTime());
183         final DateFormat dfus = DateFormat.getTimeInstance(DateFormat.SHORT, Locale.US);
184         final String valus = dfus.format(cal.getTime());
185         final Object test = TimeValidator.getInstance().validate("16:49:23", "HH:mm:ss");
186         assertNotNull(test, "Test Date ");
187         assertEquals("16-49-23", validator.format(test, "HH-mm-ss"), "Format pattern");
188         assertEquals(valus, validator.format(test, Locale.US), "Format locale");
189         assertEquals(val, validator.format(test), "Format default");
190     }
191 
192     /**
193      * Test Invalid Dates with "locale" validation
194      */
195     @Test
196     void testLocaleInvalid() {
197         for (int i = 0; i < localeInvalid.length; i++) {
198             final String text = i + " value=[" + localeInvalid[i] + "] passed ";
199             final Object date = validator.validate(localeInvalid[i], Locale.US);
200             assertNull(date, "validate() " + text + date);
201             assertFalse(validator.isValid(localeInvalid[i], Locale.UK), "isValid() " + text);
202         }
203     }
204 
205     /**
206      * Test Valid Dates with "locale" validation
207      */
208     @Test
209     void testLocaleValid() {
210         for (int i = 0; i < localeValid.length; i++) {
211             final String text = i + " value=[" + localeValid[i] + "] failed ";
212             final Calendar calendar = validator.validate(localeValid[i], Locale.UK);
213             assertNotNull(calendar, "validate() " + text);
214             final Date date = calendar.getTime();
215             assertTrue(validator.isValid(localeValid[i], Locale.UK), "isValid() " + text);
216             assertEquals(localeExpect[i], date, "compare " + text);
217         }
218     }
219 
220     /**
221      * Test Invalid Dates with "pattern" validation
222      */
223     @Test
224     void testPatternInvalid() {
225         for (int i = 0; i < patternInvalid.length; i++) {
226             final String text = i + " value=[" + patternInvalid[i] + "] passed ";
227             final Object date = validator.validate(patternInvalid[i], "HH-mm-ss");
228             assertNull(date, "validate() " + text + date);
229             assertFalse(validator.isValid(patternInvalid[i], "HH-mm-ss"), "isValid() " + text);
230         }
231     }
232 
233     /**
234      * Test Valid Dates with "pattern" validation
235      */
236     @Test
237     void testPatternValid() {
238         for (int i = 0; i < patternValid.length; i++) {
239             final String text = i + " value=[" + patternValid[i] + "] failed ";
240             final Calendar calendar = validator.validate(patternValid[i], "HH-mm-ss");
241             assertNotNull(calendar, "validateObj() " + text);
242             final Date date = calendar.getTime();
243             assertTrue(validator.isValid(patternValid[i], "HH-mm-ss"), "isValid() " + text);
244             assertEquals(patternExpect[i], date, "compare " + text);
245         }
246     }
247 
248     /**
249      * Test time zone methods.
250      */
251     @Test
252     @DefaultLocale("en-GB")
253     @DefaultTimeZone("GMT")
254     void testTimeZone() {
255         Calendar result = validator.validate("18:01");
256         assertNotNull(result, "default result");
257         assertEquals(TimeZones.GMT, result.getTimeZone(), "default zone");
258         assertEquals(18, result.get(Calendar.HOUR_OF_DAY), "default hour");
259         assertEquals(01, result.get(Calendar.MINUTE), "default minute");
260         result = null;
261 
262         // Default Locale, diff TimeZone
263         result = validator.validate("16:49", TestTimeZones.EST);
264         assertNotNull(result, "zone result");
265         assertEquals(TestTimeZones.EST, result.getTimeZone(), "zone zone");
266         assertEquals(16, result.get(Calendar.HOUR_OF_DAY), "zone hour");
267         assertEquals(49, result.get(Calendar.MINUTE), "zone minute");
268         result = null;
269 
270         // Pattern, diff TimeZone
271         result = validator.validate("14-34", "HH-mm", TestTimeZones.EST);
272         assertNotNull(result, "pattern result");
273         assertEquals(TestTimeZones.EST, result.getTimeZone(), "pattern zone");
274         assertEquals(14, result.get(Calendar.HOUR_OF_DAY), "pattern hour");
275         assertEquals(34, result.get(Calendar.MINUTE), "pattern minute");
276         result = null;
277 
278         // Locale, diff TimeZone
279         final DateFormat usdf = DateFormat.getTimeInstance(DateFormat.SHORT, Locale.US);
280         final Calendar uscal = Calendar.getInstance(Locale.US);
281         uscal.set(2005, Calendar.JANUARY, 1, 19, 18); // month is 0-based
282         final String usVal = usdf.format(uscal.getTime());
283         result = validator.validate(usVal, Locale.US, TestTimeZones.EST);
284         assertNotNull(result, "locale result: " + usVal);
285         assertEquals(TestTimeZones.EST, result.getTimeZone(), "locale zone: " + usVal);
286         assertEquals(19, result.get(Calendar.HOUR_OF_DAY), "locale hour: " + usVal);
287         assertEquals(18, result.get(Calendar.MINUTE), "locale minute: " + usVal);
288         result = null;
289 
290         final String dateTimePattern = "dd/MMM/yy HH-mm";
291         final Calendar decal = Calendar.getInstance(Locale.GERMAN);
292         decal.set(2005, 11, 31, 21, 05); // month is 0-based
293         final String germanSample = new SimpleDateFormat(dateTimePattern, Locale.GERMAN).format(decal.getTime());
294 
295         // Locale & Pattern, diff TimeZone
296         result = validator.validate(germanSample, dateTimePattern, Locale.GERMAN, TestTimeZones.EST);
297         assertNotNull(result, "pattern result: " + germanSample);
298         assertEquals(TestTimeZones.EST, result.getTimeZone(), "pattern zone");
299         assertEquals(2005, result.get(Calendar.YEAR), "pattern day");
300         assertEquals(11, result.get(Calendar.MONTH), "pattern day"); // months are 0-11
301         assertEquals(31, result.get(Calendar.DATE), "pattern day");
302         assertEquals(21, result.get(Calendar.HOUR_OF_DAY), "pattern hour");
303         assertEquals(05, result.get(Calendar.MINUTE), "pattern minute");
304         result = null;
305 
306         // Locale & Pattern, default TimeZone
307         result = validator.validate(germanSample, dateTimePattern, Locale.GERMAN);
308         assertNotNull(result, "pattern result: " + germanSample);
309         assertEquals(TimeZones.GMT, result.getTimeZone(), "pattern zone");
310         assertEquals(2005, result.get(Calendar.YEAR), "pattern day");
311         assertEquals(11, result.get(Calendar.MONTH), "pattern day"); // months are 0-11
312         assertEquals(31, result.get(Calendar.DATE), "pattern day");
313         assertEquals(21, result.get(Calendar.HOUR_OF_DAY), "pattern hour");
314         assertEquals(05, result.get(Calendar.MINUTE), "pattern minute");
315         result = null;
316 
317     }
318 }