1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.lang3.time;
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.assertNotEquals;
22 import static org.junit.jupiter.api.Assertions.assertTrue;
23
24 import java.text.ParseException;
25 import java.text.ParsePosition;
26 import java.text.SimpleDateFormat;
27 import java.util.Date;
28 import java.util.Locale;
29 import java.util.TimeZone;
30 import java.util.stream.Stream;
31
32 import org.apache.commons.lang3.AbstractLangTest;
33 import org.junit.jupiter.params.ParameterizedTest;
34 import org.junit.jupiter.params.provider.Arguments;
35 import org.junit.jupiter.params.provider.MethodSource;
36
37
38
39
40 class FastDateParserSDFTest extends AbstractLangTest {
41
42 private static final TimeZone timeZone = TimeZone.getDefault();
43
44 public static Stream<Arguments> data() {
45
46 return Stream.of(
47
48 Arguments.of("z yyyy", "GMT 2010", Locale.UK, true),
49 Arguments.of("z yyyy", "GMT-123 2010", Locale.UK, false),
50 Arguments.of("z yyyy", "GMT-1234 2010", Locale.UK, false),
51 Arguments.of("z yyyy", "GMT-12:34 2010", Locale.UK, true),
52 Arguments.of("z yyyy", "GMT-1:23 2010", Locale.UK, true),
53
54 Arguments.of("z yyyy", "-1234 2010", Locale.UK, true),
55 Arguments.of("z yyyy", "-12:34 2010", Locale.UK, false),
56 Arguments.of("z yyyy", "-123 2010", Locale.UK, false),
57
58 Arguments.of("MM/dd/yyyy", "01/11/12", Locale.UK, true),
59 Arguments.of("MM/dd/yy", "01/11/12", Locale.UK, true),
60
61
62 Arguments.of("HH", "00", Locale.UK, true),
63 Arguments.of("KK", "00", Locale.UK, true),
64 Arguments.of("hh", "00", Locale.UK, true),
65 Arguments.of("kk", "00", Locale.UK, true),
66
67 Arguments.of("HH", "01", Locale.UK, true),
68 Arguments.of("KK", "01", Locale.UK, true),
69 Arguments.of("hh", "01", Locale.UK, true),
70 Arguments.of("kk", "01", Locale.UK, true),
71
72 Arguments.of("HH", "11", Locale.UK, true),
73 Arguments.of("KK", "11", Locale.UK, true),
74 Arguments.of("hh", "11", Locale.UK, true),
75 Arguments.of("kk", "11", Locale.UK, true),
76
77 Arguments.of("HH", "12", Locale.UK, true),
78 Arguments.of("KK", "12", Locale.UK, true),
79 Arguments.of("hh", "12", Locale.UK, true),
80 Arguments.of("kk", "12", Locale.UK, true),
81
82 Arguments.of("HH", "13", Locale.UK, true),
83 Arguments.of("KK", "13", Locale.UK, true),
84 Arguments.of("hh", "13", Locale.UK, true),
85 Arguments.of("kk", "13", Locale.UK, true),
86
87 Arguments.of("HH", "23", Locale.UK, true),
88 Arguments.of("KK", "23", Locale.UK, true),
89 Arguments.of("hh", "23", Locale.UK, true),
90 Arguments.of("kk", "23", Locale.UK, true),
91
92 Arguments.of("HH", "24", Locale.UK, true),
93 Arguments.of("KK", "24", Locale.UK, true),
94 Arguments.of("hh", "24", Locale.UK, true),
95 Arguments.of("kk", "24", Locale.UK, true),
96
97 Arguments.of("HH", "25", Locale.UK, true),
98 Arguments.of("KK", "25", Locale.UK, true),
99 Arguments.of("hh", "25", Locale.UK, true),
100 Arguments.of("kk", "25", Locale.UK, true),
101
102 Arguments.of("HH", "48", Locale.UK, true),
103 Arguments.of("KK", "48", Locale.UK, true),
104 Arguments.of("hh", "48", Locale.UK, true),
105 Arguments.of("kk", "48", Locale.UK, true)
106 );
107
108 }
109
110 private void checkParse(final String formattedDate, final String format, final Locale locale, final boolean valid) {
111 final SimpleDateFormat sdf = new SimpleDateFormat(format, locale);
112 sdf.setTimeZone(timeZone);
113 final DateParser fdf = new FastDateParser(format, timeZone, locale);
114 Date expectedTime = null;
115 Class<?> sdfE = null;
116 try {
117 expectedTime = sdf.parse(formattedDate);
118 if (!valid) {
119
120 throw new RuntimeException("Test data error: expected SDF parse to fail, but got " + expectedTime);
121 }
122 } catch (final ParseException e) {
123 if (valid) {
124
125 throw new RuntimeException("Test data error: expected SDF parse to succeed, but got " + e);
126 }
127 sdfE = e.getClass();
128 }
129 Date actualTime = null;
130 Class<?> fdfE = null;
131 try {
132 actualTime = fdf.parse(formattedDate);
133
134 assertTrue(valid, "Expected FDP parse to fail, but got " + actualTime);
135 } catch (final ParseException e) {
136
137 assertFalse(valid, "Expected FDP parse to succeed, but got " + e);
138 fdfE = e.getClass();
139 }
140 if (valid) {
141 assertEquals(expectedTime, actualTime, locale + " " + formattedDate + "\n");
142 } else {
143 assertEquals(sdfE, fdfE, locale + " " + formattedDate + " expected same Exception ");
144 }
145 }
146
147 private void checkParsePosition(final String formattedDate, final String format, final Locale locale, final boolean valid) {
148 final SimpleDateFormat sdf = new SimpleDateFormat(format, locale);
149 sdf.setTimeZone(timeZone);
150 final DateParser fdf = new FastDateParser(format, timeZone, locale);
151
152 final ParsePosition sdfP = new ParsePosition(0);
153 final Date expectedTime = sdf.parse(formattedDate, sdfP);
154 final int sdferrorIndex = sdfP.getErrorIndex();
155 if (valid) {
156 assertEquals(-1, sdferrorIndex, "Expected SDF error index -1 ");
157 final int endIndex = sdfP.getIndex();
158 final int length = formattedDate.length();
159 if (endIndex != length) {
160
161 throw new RuntimeException("Test data error: expected SDF parse to consume entire string; endindex " + endIndex + " != " + length);
162 }
163 } else {
164 final int errorIndex = sdfP.getErrorIndex();
165 if (errorIndex == -1) {
166 throw new RuntimeException("Test data error: expected SDF parse to fail, but got " + expectedTime);
167 }
168 }
169
170 final ParsePosition fdfP = new ParsePosition(0);
171 final Date actualTime = fdf.parse(formattedDate, fdfP);
172 final int fdferrorIndex = fdfP.getErrorIndex();
173 if (valid) {
174 assertEquals(-1, fdferrorIndex, "Expected FDF error index -1 ");
175 final int endIndex = fdfP.getIndex();
176 final int length = formattedDate.length();
177 assertEquals(length, endIndex, "Expected FDF to parse full string " + fdfP);
178 assertEquals(expectedTime, actualTime, locale + " " + formattedDate + "\n");
179 } else {
180 assertNotEquals(-1, fdferrorIndex, "Test data error: expected FDF parse to fail, but got " + actualTime);
181 assertTrue(sdferrorIndex - fdferrorIndex <= 4, "FDF error index (" + fdferrorIndex + ") should approximate SDF index (" + sdferrorIndex + ")");
182 }
183 }
184
185 @ParameterizedTest
186 @MethodSource("data")
187 void testLowerCase(final String format, final String input, final Locale locale, final boolean valid) {
188 checkParse(input.toLowerCase(locale), format, locale, valid);
189 }
190
191 @ParameterizedTest
192 @MethodSource("data")
193 void testLowerCasePP(final String format, final String input, final Locale locale, final boolean valid) {
194 checkParsePosition(input.toLowerCase(locale), format, locale, valid);
195 }
196
197 @ParameterizedTest
198 @MethodSource("data")
199 void testOriginal(final String format, final String input, final Locale locale, final boolean valid) {
200 checkParse(input, format, locale, valid);
201 }
202
203 @ParameterizedTest
204 @MethodSource("data")
205 void testOriginalPP(final String format, final String input, final Locale locale, final boolean valid) {
206 checkParsePosition(input, format, locale, valid);
207 }
208
209 @ParameterizedTest
210 @MethodSource("data")
211 void testUpperCase(final String format, final String input, final Locale locale, final boolean valid) {
212 checkParse(input.toUpperCase(locale), format, locale, valid);
213 }
214 @ParameterizedTest
215 @MethodSource("data")
216 void testUpperCasePP(final String format, final String input, final Locale locale, final boolean valid) {
217 checkParsePosition(input.toUpperCase(locale), format, locale, valid);
218 }
219 }