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.assertNotEquals;
21 import static org.junit.jupiter.api.Assertions.assertNotSame;
22 import static org.junit.jupiter.api.Assertions.assertSame;
23 import static org.junit.jupiter.api.Assertions.fail;
24
25 import java.text.FieldPosition;
26 import java.text.Format;
27 import java.text.ParsePosition;
28 import java.text.SimpleDateFormat;
29 import java.time.Instant;
30 import java.time.LocalDate;
31 import java.time.ZoneId;
32 import java.util.Date;
33 import java.util.Locale;
34 import java.util.TimeZone;
35 import java.util.concurrent.ExecutorService;
36 import java.util.concurrent.Executors;
37 import java.util.concurrent.TimeUnit;
38 import java.util.concurrent.atomic.AtomicInteger;
39 import java.util.concurrent.atomic.AtomicLongArray;
40
41 import org.apache.commons.lang3.AbstractLangTest;
42 import org.junit.jupiter.api.Test;
43 import org.junitpioneer.jupiter.DefaultLocale;
44 import org.junitpioneer.jupiter.DefaultTimeZone;
45
46
47
48
49
50
51 public class FastDateFormatTest extends AbstractLangTest {
52 private static final int NTHREADS = 10;
53
54 private static final int NROUNDS = 10000;
55
56 final Locale FINNISH = Locale.forLanguageTag("fi");
57 final Locale HUNGARIAN = Locale.forLanguageTag("hu");
58
59 private AtomicLongArray measureTime(final Format printer, final Format parser) throws InterruptedException {
60 final ExecutorService pool = Executors.newFixedThreadPool(NTHREADS);
61 final AtomicInteger failures = new AtomicInteger(0);
62 final AtomicLongArray totalElapsed = new AtomicLongArray(2);
63 try {
64 for (int i = 0; i < NTHREADS; ++i) {
65 pool.submit(() -> {
66 for (int j = 0; j < NROUNDS; ++j) {
67 try {
68 final Date date = new Date();
69
70 final long t0Millis = System.currentTimeMillis();
71 final String formattedDate = printer.format(date);
72 totalElapsed.addAndGet(0, System.currentTimeMillis() - t0Millis);
73
74 final long t1Millis = System.currentTimeMillis();
75 final Object pd = parser.parseObject(formattedDate);
76 totalElapsed.addAndGet(1, System.currentTimeMillis() - t1Millis);
77
78 if (!date.equals(pd)) {
79 failures.incrementAndGet();
80 }
81 } catch (final Exception e) {
82 failures.incrementAndGet();
83 e.printStackTrace();
84 }
85 }
86 });
87 }
88 } finally {
89 pool.shutdown();
90
91
92
93 if (!pool.awaitTermination(30, TimeUnit.SECONDS)) {
94 pool.shutdownNow();
95 fail("did not complete tasks");
96 }
97 }
98 assertEquals(0, failures.get());
99 return totalElapsed;
100 }
101
102 @DefaultLocale(language = "en", country = "US")
103 @Test
104 public void test_changeDefault_Locale_DateInstance() {
105 final FastDateFormat format1 = FastDateFormat.getDateInstance(FastDateFormat.FULL, Locale.GERMANY);
106 final FastDateFormat format2 = FastDateFormat.getDateInstance(FastDateFormat.FULL);
107 Locale.setDefault(Locale.GERMANY);
108 final FastDateFormat format3 = FastDateFormat.getDateInstance(FastDateFormat.FULL);
109
110 assertSame(Locale.GERMANY, format1.getLocale());
111 assertEquals(Locale.US, format2.getLocale());
112 assertSame(Locale.GERMANY, format3.getLocale());
113 assertNotSame(format1, format2);
114 assertNotSame(format2, format3);
115 }
116
117 @DefaultLocale(language = "en", country = "US")
118 @Test
119 public void test_changeDefault_Locale_DateTimeInstance() {
120 final FastDateFormat format1 = FastDateFormat.getDateTimeInstance(FastDateFormat.FULL, FastDateFormat.FULL, Locale.GERMANY);
121 final FastDateFormat format2 = FastDateFormat.getDateTimeInstance(FastDateFormat.FULL, FastDateFormat.FULL);
122 Locale.setDefault(Locale.GERMANY);
123 final FastDateFormat format3 = FastDateFormat.getDateTimeInstance(FastDateFormat.FULL, FastDateFormat.FULL);
124
125 assertSame(Locale.GERMANY, format1.getLocale());
126 assertEquals(Locale.US, format2.getLocale());
127 assertSame(Locale.GERMANY, format3.getLocale());
128 assertNotSame(format1, format2);
129 assertNotSame(format2, format3);
130 }
131
132
133
134
135
136
137 @Test
138 public void test_getInstance() {
139 final FastDateFormat format1 = FastDateFormat.getInstance();
140 final FastDateFormat format2 = FastDateFormat.getInstance();
141 assertSame(format1, format2);
142 }
143
144 @Test
145 public void test_getInstance_String() {
146 final FastDateFormat format1 = FastDateFormat.getInstance("MM/DD/yyyy");
147 final FastDateFormat format2 = FastDateFormat.getInstance("MM-DD-yyyy");
148 final FastDateFormat format3 = FastDateFormat.getInstance("MM-DD-yyyy");
149
150 assertNotSame(format1, format2);
151 assertSame(format2, format3);
152 assertEquals("MM/DD/yyyy", format1.getPattern());
153 assertEquals(TimeZone.getDefault(), format1.getTimeZone());
154 assertEquals(TimeZone.getDefault(), format2.getTimeZone());
155 }
156
157 @DefaultLocale(language = "en", country = "US")
158 @Test
159 public void test_getInstance_String_Locale() {
160 final FastDateFormat format1 = FastDateFormat.getInstance("MM/DD/yyyy", Locale.GERMANY);
161 final FastDateFormat format2 = FastDateFormat.getInstance("MM/DD/yyyy");
162 final FastDateFormat format3 = FastDateFormat.getInstance("MM/DD/yyyy", Locale.GERMANY);
163
164 assertNotSame(format1, format2);
165 assertSame(format1, format3);
166 assertEquals(Locale.GERMANY, format1.getLocale());
167 }
168
169 @DefaultLocale(language = "en", country = "US")
170 @DefaultTimeZone("America/New_York")
171 @Test
172 public void test_getInstance_String_TimeZone() {
173
174 final FastDateFormat format1 = FastDateFormat.getInstance("MM/DD/yyyy",
175 TimeZone.getTimeZone("Atlantic/Reykjavik"));
176 final FastDateFormat format2 = FastDateFormat.getInstance("MM/DD/yyyy");
177 final FastDateFormat format3 = FastDateFormat.getInstance("MM/DD/yyyy", TimeZone.getDefault());
178 final FastDateFormat format4 = FastDateFormat.getInstance("MM/DD/yyyy", TimeZone.getDefault());
179 final FastDateFormat format5 = FastDateFormat.getInstance("MM-DD-yyyy", TimeZone.getDefault());
180 final FastDateFormat format6 = FastDateFormat.getInstance("MM-DD-yyyy");
181
182 assertNotSame(format1, format2);
183 assertEquals(TimeZone.getTimeZone("Atlantic/Reykjavik"), format1.getTimeZone());
184 assertEquals(TimeZone.getDefault(), format2.getTimeZone());
185 assertSame(format3, format4);
186 assertNotSame(format3, format5);
187 assertNotSame(format4, format6);
188 }
189
190 @DefaultLocale(language = "en", country = "US")
191 @DefaultTimeZone("America/New_York")
192 @Test
193 public void test_getInstance_String_TimeZone_Locale() {
194 final FastDateFormat format1 = FastDateFormat.getInstance("MM/DD/yyyy",
195 TimeZone.getTimeZone("Atlantic/Reykjavik"), Locale.GERMANY);
196 final FastDateFormat format2 = FastDateFormat.getInstance("MM/DD/yyyy", Locale.GERMANY);
197 final FastDateFormat format3 = FastDateFormat.getInstance("MM/DD/yyyy",
198 TimeZone.getDefault(), Locale.GERMANY);
199
200 assertNotSame(format1, format2);
201 assertEquals(TimeZone.getTimeZone("Atlantic/Reykjavik"), format1.getTimeZone());
202 assertEquals(TimeZone.getDefault(), format2.getTimeZone());
203 assertEquals(TimeZone.getDefault(), format3.getTimeZone());
204 assertEquals(Locale.GERMANY, format1.getLocale());
205 assertEquals(Locale.GERMANY, format2.getLocale());
206 assertEquals(Locale.GERMANY, format3.getLocale());
207 }
208
209 @Test
210 public void testCheckDefaults() {
211 final FastDateFormat format = FastDateFormat.getInstance();
212 final FastDateFormat medium = FastDateFormat.getDateTimeInstance(FastDateFormat.SHORT, FastDateFormat.SHORT);
213 assertEquals(medium, format);
214
215 final SimpleDateFormat sdf = new SimpleDateFormat();
216 assertEquals(sdf.toPattern(), format.getPattern());
217
218 assertEquals(Locale.getDefault(), format.getLocale());
219 assertEquals(TimeZone.getDefault(), format.getTimeZone());
220 }
221
222 @Test
223 public void testCheckDifferingStyles() {
224 final FastDateFormat shortShort = FastDateFormat.getDateTimeInstance(FastDateFormat.SHORT, FastDateFormat.SHORT, Locale.US);
225 final FastDateFormat shortLong = FastDateFormat.getDateTimeInstance(FastDateFormat.SHORT, FastDateFormat.LONG, Locale.US);
226 final FastDateFormat longShort = FastDateFormat.getDateTimeInstance(FastDateFormat.LONG, FastDateFormat.SHORT, Locale.US);
227 final FastDateFormat longLong = FastDateFormat.getDateTimeInstance(FastDateFormat.LONG, FastDateFormat.LONG, Locale.US);
228
229 assertNotEquals(shortShort, shortLong);
230 assertNotEquals(shortShort, longShort);
231 assertNotEquals(shortShort, longLong);
232 assertNotEquals(shortLong, longShort);
233 assertNotEquals(shortLong, longLong);
234 assertNotEquals(longShort, longLong);
235 }
236
237 @Test
238 public void testDateDefaults() {
239 assertEquals(FastDateFormat.getDateInstance(FastDateFormat.LONG, Locale.CANADA),
240 FastDateFormat.getDateInstance(FastDateFormat.LONG, TimeZone.getDefault(), Locale.CANADA));
241
242 assertEquals(FastDateFormat.getDateInstance(FastDateFormat.LONG, TimeZone.getTimeZone("America/New_York")),
243 FastDateFormat.getDateInstance(FastDateFormat.LONG, TimeZone.getTimeZone("America/New_York"), Locale.getDefault()));
244
245 assertEquals(FastDateFormat.getDateInstance(FastDateFormat.LONG),
246 FastDateFormat.getDateInstance(FastDateFormat.LONG, TimeZone.getDefault(), Locale.getDefault()));
247 }
248
249 @Test
250 public void testLANG_1152() {
251 final TimeZone utc = FastTimeZone.getGmtTimeZone();
252 final Date date = new Date(Long.MAX_VALUE);
253
254 String dateAsString = FastDateFormat.getInstance("yyyy-MM-dd", utc, Locale.US).format(date);
255 assertEquals("292278994-08-17", dateAsString);
256
257 dateAsString = FastDateFormat.getInstance("dd/MM/yyyy", utc, Locale.US).format(date);
258 assertEquals("17/08/292278994", dateAsString);
259 }
260 @Test
261 public void testLANG_1267() {
262 FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
263 }
264
265
266
267
268 @Test
269 public void testLANG_954() {
270 final String pattern = "yyyy-MM-dd'T'";
271 FastDateFormat.getInstance(pattern);
272 }
273
274 @Test
275 public void testParseSync() throws InterruptedException {
276 final String pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS";
277 final SimpleDateFormat inner = new SimpleDateFormat(pattern);
278 final Format sdf= new Format() {
279 private static final long serialVersionUID = 1L;
280
281 @Override
282 public StringBuffer format(final Object obj,
283 final StringBuffer toAppendTo,
284 final FieldPosition fieldPosition) {
285 synchronized (this) {
286 return inner.format(obj, toAppendTo, fieldPosition);
287 }
288 }
289
290 @Override
291 public Object parseObject(final String source, final ParsePosition pos) {
292 synchronized (this) {
293 return inner.parseObject(source, pos);
294 }
295 }
296 };
297 final AtomicLongArray sdfTime= measureTime(sdf, sdf);
298
299 final Format fdf = FastDateFormat.getInstance(pattern);
300 final AtomicLongArray fdfTime= measureTime(fdf, fdf);
301
302
303
304 }
305
306 @Test
307 public void testStandaloneLongMonthForm() {
308 final TimeZone utc = FastTimeZone.getGmtTimeZone();
309 final Instant testInstant = LocalDate.of(1970, 9, 15).atStartOfDay(ZoneId.of("UTC")).toInstant();
310 final Date date = Date.from(testInstant);
311
312 String dateAsString = FastDateFormat.getInstance("yyyy-LLLL-dd", utc, Locale.GERMAN).format(date);
313 assertEquals("1970-September-15", dateAsString);
314
315 dateAsString = FastDateFormat.getInstance("yyyy-LLLL-dd", utc, FINNISH).format(date);
316 assertEquals("1970-syyskuu-15", dateAsString);
317
318 dateAsString = FastDateFormat.getInstance("yyyy-LLLL-dd", utc, HUNGARIAN).format(date);
319 assertEquals("1970-szeptember-15", dateAsString);
320 }
321
322 @Test
323 public void testStandaloneShortMonthForm() {
324 final TimeZone utc = FastTimeZone.getGmtTimeZone();
325 final Instant testInstant = LocalDate.of(1970, 9, 15).atStartOfDay(ZoneId.of("UTC")).toInstant();
326 final Date date = Date.from(testInstant);
327
328 String dateAsString = FastDateFormat.getInstance("yyyy-LLL-dd", utc, Locale.GERMAN).format(date);
329 assertEquals("1970-Sep-15", dateAsString);
330
331 dateAsString = FastDateFormat.getInstance("yyyy-LLL-dd", utc, FINNISH).format(date);
332 assertEquals("1970-syys-15", dateAsString);
333
334 dateAsString = FastDateFormat.getInstance("yyyy-LLL-dd", utc, HUNGARIAN).format(date);
335 assertEquals("1970-szept.-15", dateAsString);
336 }
337
338 @Test
339 public void testTimeDateDefaults() {
340 assertEquals(FastDateFormat.getDateTimeInstance(FastDateFormat.LONG, FastDateFormat.MEDIUM, Locale.CANADA),
341 FastDateFormat.getDateTimeInstance(FastDateFormat.LONG, FastDateFormat.MEDIUM, TimeZone.getDefault(), Locale.CANADA));
342
343 assertEquals(FastDateFormat.getDateTimeInstance(FastDateFormat.LONG, FastDateFormat.MEDIUM, TimeZone.getTimeZone("America/New_York")),
344 FastDateFormat.getDateTimeInstance(FastDateFormat.LONG, FastDateFormat.MEDIUM, TimeZone.getTimeZone("America/New_York"), Locale.getDefault()));
345
346 assertEquals(FastDateFormat.getDateTimeInstance(FastDateFormat.LONG, FastDateFormat.MEDIUM),
347 FastDateFormat.getDateTimeInstance(FastDateFormat.LONG, FastDateFormat.MEDIUM, TimeZone.getDefault(), Locale.getDefault()));
348 }
349
350 @Test
351 public void testTimeDefaults() {
352 assertEquals(FastDateFormat.getTimeInstance(FastDateFormat.LONG, Locale.CANADA),
353 FastDateFormat.getTimeInstance(FastDateFormat.LONG, TimeZone.getDefault(), Locale.CANADA));
354
355 assertEquals(FastDateFormat.getTimeInstance(FastDateFormat.LONG, TimeZone.getTimeZone("America/New_York")),
356 FastDateFormat.getTimeInstance(FastDateFormat.LONG, TimeZone.getTimeZone("America/New_York"), Locale.getDefault()));
357
358 assertEquals(FastDateFormat.getTimeInstance(FastDateFormat.LONG),
359 FastDateFormat.getTimeInstance(FastDateFormat.LONG, TimeZone.getDefault(), Locale.getDefault()));
360 }
361 }