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.assertNotNull;
22 import static org.junit.jupiter.api.Assertions.assertNotSame;
23 import static org.junit.jupiter.api.Assertions.assertSame;
24 import static org.junit.jupiter.api.Assertions.fail;
25
26 import java.text.FieldPosition;
27 import java.text.Format;
28 import java.text.ParseException;
29 import java.text.ParsePosition;
30 import java.text.SimpleDateFormat;
31 import java.time.Instant;
32 import java.time.LocalDate;
33 import java.time.ZoneId;
34 import java.time.format.DateTimeFormatter;
35 import java.util.Calendar;
36 import java.util.Date;
37 import java.util.Locale;
38 import java.util.SimpleTimeZone;
39 import java.util.TimeZone;
40 import java.util.concurrent.ExecutorService;
41 import java.util.concurrent.Executors;
42 import java.util.concurrent.TimeUnit;
43 import java.util.concurrent.atomic.AtomicInteger;
44 import java.util.concurrent.atomic.AtomicLongArray;
45
46 import org.apache.commons.lang3.AbstractLangTest;
47 import org.junit.jupiter.api.Test;
48 import org.junitpioneer.jupiter.DefaultLocale;
49 import org.junitpioneer.jupiter.DefaultTimeZone;
50 import org.junitpioneer.jupiter.ReadsDefaultLocale;
51 import org.junitpioneer.jupiter.ReadsDefaultTimeZone;
52
53
54
55
56 class FastDateFormatTest extends AbstractLangTest {
57
58 private static final String ISO_8601_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ssZZ";
59
60 private static final int NTHREADS = 10;
61
62 private static final int NROUNDS = 10000;
63
64 final Locale FINNISH = Locale.forLanguageTag("fi");
65 final Locale HUNGARIAN = Locale.forLanguageTag("hu");
66
67 private void assertCalendar(final TimeZone expectedTimeZone, final Date expectedDate, final Calendar actual) {
68 assertSame(expectedTimeZone, actual.getTimeZone());
69
70 assertEquals(expectedDate, actual.getTime());
71 }
72
73 private AtomicLongArray measureTime(final Format printer, final Format parser) throws InterruptedException {
74 final ExecutorService pool = Executors.newFixedThreadPool(NTHREADS);
75 final AtomicInteger failures = new AtomicInteger();
76 final AtomicLongArray totalElapsed = new AtomicLongArray(2);
77 try {
78 for (int i = 0; i < NTHREADS; ++i) {
79 pool.submit(() -> {
80 for (int j = 0; j < NROUNDS; ++j) {
81 try {
82 final Date date = new Date();
83
84 final long t0Millis = System.currentTimeMillis();
85 final String formattedDate = printer.format(date);
86 totalElapsed.addAndGet(0, System.currentTimeMillis() - t0Millis);
87
88 final long t1Millis = System.currentTimeMillis();
89 final Object pd = parser.parseObject(formattedDate);
90 totalElapsed.addAndGet(1, System.currentTimeMillis() - t1Millis);
91
92 if (!date.equals(pd)) {
93 failures.incrementAndGet();
94 }
95 } catch (final Exception e) {
96 failures.incrementAndGet();
97 e.printStackTrace();
98 }
99 }
100 });
101 }
102 } finally {
103 pool.shutdown();
104
105
106
107 if (!pool.awaitTermination(30, TimeUnit.SECONDS)) {
108 pool.shutdownNow();
109 fail("did not complete tasks");
110 }
111 }
112 assertEquals(0, failures.get());
113 return totalElapsed;
114 }
115
116 @DefaultLocale(language = "en", country = "US")
117 @Test
118 void test_changeDefault_Locale_DateInstance() {
119 final FastDateFormat format1 = FastDateFormat.getDateInstance(FastDateFormat.FULL, Locale.GERMANY);
120 final FastDateFormat format2 = FastDateFormat.getDateInstance(FastDateFormat.FULL);
121 Locale.setDefault(Locale.GERMANY);
122 final FastDateFormat format3 = FastDateFormat.getDateInstance(FastDateFormat.FULL);
123
124 assertSame(Locale.GERMANY, format1.getLocale());
125 assertEquals(Locale.US, format2.getLocale());
126 assertSame(Locale.GERMANY, format3.getLocale());
127 assertNotSame(format1, format2);
128 assertNotSame(format2, format3);
129 }
130
131 @DefaultLocale(language = "en", country = "US")
132 @Test
133 void test_changeDefault_Locale_DateTimeInstance() {
134 final FastDateFormat format1 = FastDateFormat.getDateTimeInstance(FastDateFormat.FULL, FastDateFormat.FULL, Locale.GERMANY);
135 final FastDateFormat format2 = FastDateFormat.getDateTimeInstance(FastDateFormat.FULL, FastDateFormat.FULL);
136 Locale.setDefault(Locale.GERMANY);
137 final FastDateFormat format3 = FastDateFormat.getDateTimeInstance(FastDateFormat.FULL, FastDateFormat.FULL);
138
139 assertSame(Locale.GERMANY, format1.getLocale());
140 assertEquals(Locale.US, format2.getLocale());
141 assertSame(Locale.GERMANY, format3.getLocale());
142 assertNotSame(format1, format2);
143 assertNotSame(format2, format3);
144 }
145
146
147
148
149
150
151 @Test
152 void test_getInstance() {
153 final FastDateFormat format1 = FastDateFormat.getInstance();
154 final FastDateFormat format2 = FastDateFormat.getInstance();
155 assertSame(format1, format2);
156 }
157
158 @Test
159 void test_getInstance_String() {
160 final FastDateFormat format1 = FastDateFormat.getInstance("MM/DD/yyyy");
161 final FastDateFormat format2 = FastDateFormat.getInstance("MM-DD-yyyy");
162 final FastDateFormat format3 = FastDateFormat.getInstance("MM-DD-yyyy");
163 assertNotSame(format1, format2);
164 assertSame(format2, format3);
165 assertEquals("MM/DD/yyyy", format1.getPattern());
166 assertEquals(TimeZone.getDefault(), format1.getTimeZone());
167 assertEquals(TimeZone.getDefault(), format2.getTimeZone());
168 assertNotNull(FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mm:ssZ"));
169 }
170
171 @DefaultLocale(language = "en", country = "US")
172 @Test
173 void test_getInstance_String_Locale() {
174 final FastDateFormat format1 = FastDateFormat.getInstance("MM/DD/yyyy", Locale.GERMANY);
175 final FastDateFormat format2 = FastDateFormat.getInstance("MM/DD/yyyy");
176 final FastDateFormat format3 = FastDateFormat.getInstance("MM/DD/yyyy", Locale.GERMANY);
177
178 assertNotSame(format1, format2);
179 assertSame(format1, format3);
180 assertEquals(Locale.GERMANY, format1.getLocale());
181 }
182
183 @DefaultLocale(language = "en", country = "US")
184 @DefaultTimeZone("America/New_York")
185 @Test
186 void test_getInstance_String_TimeZone() {
187
188 final FastDateFormat format1 = FastDateFormat.getInstance("MM/DD/yyyy",
189 TimeZones.getTimeZone("Atlantic/Reykjavik"));
190 final FastDateFormat format2 = FastDateFormat.getInstance("MM/DD/yyyy");
191 final FastDateFormat format3 = FastDateFormat.getInstance("MM/DD/yyyy", TimeZone.getDefault());
192 final FastDateFormat format4 = FastDateFormat.getInstance("MM/DD/yyyy", TimeZone.getDefault());
193 final FastDateFormat format5 = FastDateFormat.getInstance("MM-DD-yyyy", TimeZone.getDefault());
194 final FastDateFormat format6 = FastDateFormat.getInstance("MM-DD-yyyy");
195
196 assertNotSame(format1, format2);
197 assertEquals(TimeZones.getTimeZone("Atlantic/Reykjavik"), format1.getTimeZone());
198 assertEquals(TimeZone.getDefault(), format2.getTimeZone());
199 assertSame(format3, format4);
200 assertNotSame(format3, format5);
201 assertNotSame(format4, format6);
202 }
203
204 @DefaultLocale(language = "en", country = "US")
205 @DefaultTimeZone("America/New_York")
206 @Test
207 void test_getInstance_String_TimeZone_Locale() {
208 final FastDateFormat format1 = FastDateFormat.getInstance("MM/DD/yyyy",
209 TimeZones.getTimeZone("Atlantic/Reykjavik"), Locale.GERMANY);
210 final FastDateFormat format2 = FastDateFormat.getInstance("MM/DD/yyyy", Locale.GERMANY);
211 final FastDateFormat format3 = FastDateFormat.getInstance("MM/DD/yyyy",
212 TimeZone.getDefault(), Locale.GERMANY);
213
214 assertNotSame(format1, format2);
215 assertEquals(TimeZones.getTimeZone("Atlantic/Reykjavik"), format1.getTimeZone());
216 assertEquals(TimeZone.getDefault(), format2.getTimeZone());
217 assertEquals(TimeZone.getDefault(), format3.getTimeZone());
218 assertEquals(Locale.GERMANY, format1.getLocale());
219 assertEquals(Locale.GERMANY, format2.getLocale());
220 assertEquals(Locale.GERMANY, format3.getLocale());
221 }
222
223
224
225
226
227 @Test
228 void test_instanceCacheIsBounded() {
229 FastDateFormat.clear();
230 final FastDateFormat first = FastDateFormat.getInstance("yyyy-MM-dd");
231 assertSame(first, FastDateFormat.getInstance("yyyy-MM-dd"));
232
233 for (int i = 0; i <= AbstractFormatCache.MAX_CACHE_SIZE; i++) {
234 FastDateFormat.getInstance("'p" + i + "'yyyy");
235 }
236 assertNotSame(first, FastDateFormat.getInstance("yyyy-MM-dd"), "Cache was not flushed at its bound");
237 FastDateFormat.clear();
238 }
239
240
241
242
243 @Test
244 void test_publicClearCache() {
245 final FastDateFormat format1 = FastDateFormat.getInstance("yyyy-MM-dd'T'HH");
246 assertSame(format1, FastDateFormat.getInstance("yyyy-MM-dd'T'HH"));
247 FastDateFormat.clear();
248 final FastDateFormat format2 = FastDateFormat.getInstance("yyyy-MM-dd'T'HH");
249 assertNotSame(format1, format2);
250 assertEquals(format1, format2);
251 }
252
253 @Test
254 @ReadsDefaultLocale
255 @ReadsDefaultTimeZone
256 void testCheckDefaults() {
257 final FastDateFormat format = FastDateFormat.getInstance();
258 final FastDateFormat medium = FastDateFormat.getDateTimeInstance(FastDateFormat.SHORT, FastDateFormat.SHORT);
259 assertEquals(medium, format);
260 final SimpleDateFormat sdf = new SimpleDateFormat();
261 assertEquals(sdf.toPattern(), format.getPattern());
262 assertEquals(Locale.getDefault(), format.getLocale());
263 assertEquals(TimeZone.getDefault(), format.getTimeZone());
264 }
265
266 @Test
267 void testCheckDifferingStyles() {
268 final FastDateFormat shortShort = FastDateFormat.getDateTimeInstance(FastDateFormat.SHORT, FastDateFormat.SHORT, Locale.US);
269 final FastDateFormat shortLong = FastDateFormat.getDateTimeInstance(FastDateFormat.SHORT, FastDateFormat.LONG, Locale.US);
270 final FastDateFormat longShort = FastDateFormat.getDateTimeInstance(FastDateFormat.LONG, FastDateFormat.SHORT, Locale.US);
271 final FastDateFormat longLong = FastDateFormat.getDateTimeInstance(FastDateFormat.LONG, FastDateFormat.LONG, Locale.US);
272
273 assertNotEquals(shortShort, shortLong);
274 assertNotEquals(shortShort, longShort);
275 assertNotEquals(shortShort, longLong);
276 assertNotEquals(shortLong, longShort);
277 assertNotEquals(shortLong, longLong);
278 assertNotEquals(longShort, longLong);
279 }
280
281 @Test
282 @ReadsDefaultLocale
283 @ReadsDefaultTimeZone
284 void testDateDefaults() {
285 assertEquals(FastDateFormat.getDateInstance(FastDateFormat.LONG, Locale.CANADA),
286 FastDateFormat.getDateInstance(FastDateFormat.LONG, TimeZone.getDefault(), Locale.CANADA));
287 assertEquals(FastDateFormat.getDateInstance(FastDateFormat.LONG, TimeZones.getTimeZone("America/New_York")),
288 FastDateFormat.getDateInstance(FastDateFormat.LONG, TimeZones.getTimeZone("America/New_York"), Locale.getDefault()));
289 assertEquals(FastDateFormat.getDateInstance(FastDateFormat.LONG),
290 FastDateFormat.getDateInstance(FastDateFormat.LONG, TimeZone.getDefault(), Locale.getDefault()));
291 }
292
293
294
295
296
297
298
299
300
301
302 @Test
303 void testGregorianCalendarWeekYearWorks() {
304 final Calendar cal = Calendar.getInstance();
305 final FastDateFormat fdp = FastDateFormat.getInstance("YYYY-MM-dd");
306 assertNotNull(fdp.format(cal), "Formatting Gregorian Calendar with YYYY pattern should always work");
307 }
308
309
310
311
312
313
314
315 @Test
316 void testJapaneseImperialCalendarWeekYearDoesNotThrow() {
317 final Locale japaneseImperial = new Locale("ja", "JP", "JP");
318 final Calendar japaneseCal = Calendar.getInstance(japaneseImperial);
319 final FastDateFormat fdp = FastDateFormat.getInstance("YYYY-MM-dd");
320 assertNotNull(fdp.format(japaneseCal), "Formatting JapaneseImperialCalendar with YYYY pattern must not throw UnsupportedOperationException");
321 }
322
323 @Test
324 void testLang1152() {
325 final TimeZone utc = FastTimeZone.getGmtTimeZone();
326 final Date date = new Date(Long.MAX_VALUE);
327
328 String dateAsString = FastDateFormat.getInstance("yyyy-MM-dd", utc, Locale.US).format(date);
329 assertEquals("292278994-08-17", dateAsString);
330
331 dateAsString = FastDateFormat.getInstance("dd/MM/yyyy", utc, Locale.US).format(date);
332 assertEquals("17/08/292278994", dateAsString);
333 }
334 @Test
335 void testLang1267() {
336 FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
337 }
338
339 @Test
340 void testLang1641() {
341 assertSame(FastDateFormat.getInstance(ISO_8601_DATE_FORMAT), FastDateFormat.getInstance(ISO_8601_DATE_FORMAT));
342
343 assertSame(FastDateFormat.getInstance(ISO_8601_DATE_FORMAT, FastTimeZone.getGmtTimeZone()),
344 FastDateFormat.getInstance(ISO_8601_DATE_FORMAT, FastTimeZone.getGmtTimeZone()));
345
346 assertSame(FastDateFormat.getInstance(ISO_8601_DATE_FORMAT, TimeZone.getDefault()),
347 FastDateFormat.getInstance(ISO_8601_DATE_FORMAT, TimeZone.getDefault()));
348
349 assertNotSame(FastDateFormat.getInstance(ISO_8601_DATE_FORMAT, TimeZones.getTimeZone("Australia/Broken_Hill")),
350 FastDateFormat.getInstance(ISO_8601_DATE_FORMAT, TimeZones.getTimeZone("Australia/Yancowinna")));
351 }
352
353
354
355
356 @Test
357 @DefaultTimeZone("America/Toronto")
358 void testLang1791() {
359 final Instant now = Instant.now();
360 final String pattern = "yyyyMMddHH";
361 final FastDateFormat gmtFormatter = FastDateFormat.getInstance(pattern, TimeZones.GMT);
362 final Calendar gmtCal = Calendar.getInstance(TimeZones.GMT);
363 final TimeZone timeZone = gmtCal.getTimeZone();
364 final Date date = gmtCal.getTime();
365 final String gmtString = gmtFormatter.format(gmtCal);
366
367 assertCalendar(timeZone, date, gmtCal);
368 assertEquals(DateTimeFormatter.ofPattern(pattern).withZone(ZoneId.of("GMT")).format(now), gmtString);
369 final FastDateFormat defaultFormatter = FastDateFormat.getInstance(pattern);
370 final String defaultString = defaultFormatter.format(gmtCal);
371
372 assertCalendar(timeZone, date, gmtCal);
373 assertEquals(DateTimeFormatter.ofPattern(pattern).withZone(ZoneId.systemDefault()).format(now), defaultString);
374 }
375
376
377
378
379 @Test
380 void testLang954() {
381 final String pattern = "yyyy-MM-dd'T'";
382 FastDateFormat.getInstance(pattern);
383 }
384
385
386
387
388
389
390 @Test
391 void testParseCentralEuropeanSummerTime() throws ParseException {
392 assertNotNull(FastDateFormat.getInstance("dd.MM.yyyy HH:mm:ss", Locale.GERMANY).parse("26.10.2014 02:00:00"));
393 assertNotNull(FastDateFormat.getInstance("dd.MM.yyyy HH:mm:ss z", Locale.US).parse("26.10.2014 02:00:00 CEST"));
394 assertNotNull(FastDateFormat.getInstance("dd.MM.yyyy HH:mm:ss z", Locale.GERMANY).parse("26.10.2014 02:00:00 MESZ"));
395 }
396
397 @Test
398 void testParseSync() throws InterruptedException {
399 final String pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS";
400 final SimpleDateFormat inner = new SimpleDateFormat(pattern);
401 final Format sdf = new Format() {
402 private static final long serialVersionUID = 1L;
403
404 @Override
405 public StringBuffer format(final Object obj, final StringBuffer toAppendTo, final FieldPosition fieldPosition) {
406 synchronized (this) {
407 return inner.format(obj, toAppendTo, fieldPosition);
408 }
409 }
410
411 @Override
412 public Object parseObject(final String source, final ParsePosition pos) {
413 synchronized (this) {
414 return inner.parseObject(source, pos);
415 }
416 }
417 };
418 final AtomicLongArray sdfTime = measureTime(sdf, sdf);
419
420 final Format fdf = FastDateFormat.getInstance(pattern);
421 final AtomicLongArray fdfTime = measureTime(fdf, fdf);
422
423
424
425 }
426
427 @Test
428 void testStandaloneLongMonthForm() {
429 final TimeZone utc = FastTimeZone.getGmtTimeZone();
430 final Instant testInstant = LocalDate.of(1970, 9, 15).atStartOfDay(ZoneId.of("UTC")).toInstant();
431 final Date date = Date.from(testInstant);
432
433 String dateAsString = FastDateFormat.getInstance("yyyy-LLLL-dd", utc, Locale.GERMAN).format(date);
434 assertEquals("1970-September-15", dateAsString);
435
436 dateAsString = FastDateFormat.getInstance("yyyy-LLLL-dd", utc, FINNISH).format(date);
437 assertEquals("1970-syyskuu-15", dateAsString);
438
439 dateAsString = FastDateFormat.getInstance("yyyy-LLLL-dd", utc, HUNGARIAN).format(date);
440 assertEquals("1970-szeptember-15", dateAsString);
441 }
442
443 @Test
444 void testStandaloneShortMonthForm() {
445 final TimeZone utc = FastTimeZone.getGmtTimeZone();
446 final Instant testInstant = LocalDate.of(1970, 9, 15).atStartOfDay(ZoneId.of("UTC")).toInstant();
447 final Date date = Date.from(testInstant);
448
449 String dateAsString = FastDateFormat.getInstance("yyyy-LLL-dd", utc, Locale.GERMAN).format(date);
450 assertEquals("1970-Sep-15", dateAsString);
451
452 dateAsString = FastDateFormat.getInstance("yyyy-LLL-dd", utc, FINNISH).format(date);
453 assertEquals("1970-syys-15", dateAsString);
454
455 dateAsString = FastDateFormat.getInstance("yyyy-LLL-dd", utc, HUNGARIAN).format(date);
456 assertEquals("1970-szept.-15", dateAsString);
457 }
458
459 @Test
460 @ReadsDefaultLocale
461 @ReadsDefaultTimeZone
462 void testTimeDateDefaults() {
463 assertEquals(FastDateFormat.getDateTimeInstance(FastDateFormat.LONG, FastDateFormat.MEDIUM, Locale.CANADA),
464 FastDateFormat.getDateTimeInstance(FastDateFormat.LONG, FastDateFormat.MEDIUM, TimeZone.getDefault(), Locale.CANADA));
465 assertEquals(FastDateFormat.getDateTimeInstance(FastDateFormat.LONG, FastDateFormat.MEDIUM, TimeZones.getTimeZone("America/New_York")),
466 FastDateFormat.getDateTimeInstance(FastDateFormat.LONG, FastDateFormat.MEDIUM, TimeZones.getTimeZone("America/New_York"), Locale.getDefault()));
467 assertEquals(FastDateFormat.getDateTimeInstance(FastDateFormat.LONG, FastDateFormat.MEDIUM),
468 FastDateFormat.getDateTimeInstance(FastDateFormat.LONG, FastDateFormat.MEDIUM, TimeZone.getDefault(), Locale.getDefault()));
469 }
470
471 @Test
472 @ReadsDefaultLocale
473 @ReadsDefaultTimeZone
474 void testTimeDefaults() {
475 assertEquals(FastDateFormat.getTimeInstance(FastDateFormat.LONG, Locale.CANADA),
476 FastDateFormat.getTimeInstance(FastDateFormat.LONG, TimeZone.getDefault(), Locale.CANADA));
477 assertEquals(FastDateFormat.getTimeInstance(FastDateFormat.LONG, TimeZones.getTimeZone("America/New_York")),
478 FastDateFormat.getTimeInstance(FastDateFormat.LONG, TimeZones.getTimeZone("America/New_York"), Locale.getDefault()));
479 assertEquals(FastDateFormat.getTimeInstance(FastDateFormat.LONG),
480 FastDateFormat.getTimeInstance(FastDateFormat.LONG, TimeZone.getDefault(), Locale.getDefault()));
481 }
482
483
484
485
486 @Test
487 void testTimeZoneArgumentIsCopied() throws ParseException {
488 final TimeZone timeZone = TimeZones.getTimeZone("UTC");
489 final FastDateFormat printer = FastDateFormat.getInstance("yyyy-MM-dd HH:mm Z", timeZone, Locale.US);
490 final FastDateFormat parser = FastDateFormat.getInstance("yyyy-MM-dd HH:mm", timeZone, Locale.US);
491 timeZone.setRawOffset(5 * 3_600_000);
492 assertEquals(TimeZones.getTimeZone("UTC"), printer.getTimeZone());
493 assertEquals("1970-01-01 00:00 +0000", printer.format(new Date(0)));
494 assertEquals(new Date(0), parser.parse("1970-01-01 00:00"));
495 }
496
497 @Test
498 void testTimeZoneCacheKeyIsCopied() throws ParseException {
499 final SimpleTimeZone timeZone = new SimpleTimeZone(0, "CacheKeyCopy", Calendar.MARCH, 1, 0, 0, Calendar.OCTOBER, 1, 0, 0);
500 timeZone.setStartYear(2000);
501 final TimeZone originalTimeZone = (TimeZone) timeZone.clone();
502 final String pattern = "yyyy-MM-dd HH:mm";
503 final FastDateFormat original = FastDateFormat.getInstance(pattern, timeZone, Locale.US);
504 final Date date = Date.from(Instant.parse("2026-06-01T00:00:00Z"));
505 assertEquals("2026-06-01 01:00", original.format(date));
506
507
508 timeZone.setStartYear(2100);
509 final FastDateFormat changed = FastDateFormat.getInstance(pattern, (TimeZone) timeZone.clone(), Locale.US);
510 assertNotSame(original, changed);
511 assertSame(original, FastDateFormat.getInstance(pattern, originalTimeZone, Locale.US));
512 assertEquals("2026-06-01 01:00", original.format(date));
513 assertEquals("2026-06-01 00:00", changed.format(date));
514 assertEquals(date, original.parse("2026-06-01 01:00"));
515 assertEquals(date, changed.parse("2026-06-01 00:00"));
516 }
517
518
519
520
521 @Test
522 void testTimeZoneGetterReturnsCopy() throws ParseException {
523 final FastDateFormat printer = FastDateFormat.getInstance("yyyy-MM-dd HH:mm:ss Z", TimeZones.getTimeZone("UTC"), Locale.US);
524 final FastDateFormat parser = FastDateFormat.getInstance("yyyy-MM-dd HH:mm:ss", TimeZones.getTimeZone("UTC"), Locale.US);
525 printer.getTimeZone().setRawOffset(5 * 3_600_000);
526 parser.getTimeZone().setRawOffset(5 * 3_600_000);
527 assertEquals(TimeZones.getTimeZone("UTC"), printer.getTimeZone());
528 assertEquals("1970-01-01 00:00:00 +0000", printer.format(new Date(0)));
529 assertEquals(new Date(0), parser.parse("1970-01-01 00:00:00"));
530 }
531 }