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