/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.lang3.time;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.text.Format;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import org.junit.Test;
/**
* Unit tests {@link org.apache.commons.lang3.time.FastDateFormat}.
*
* @since 2.0
* @version $Id$
*/
public class FastDateFormatTest {
/*
* Only the cache methods need to be tested here.
* The print methods are tested by {@link FastDateFormat_PrinterTest}
* and the parse methods are tested by {@link FastDateFormat_ParserTest}
*/
@Test
public void test_getInstance() {
final FastDateFormat format1 = FastDateFormat.getInstance();
final FastDateFormat format2 = FastDateFormat.getInstance();
assertSame(format1, format2);
}
@Test
public void test_getInstance_String() {
final FastDateFormat format1 = FastDateFormat.getInstance("MM/DD/yyyy");
final FastDateFormat format2 = FastDateFormat.getInstance("MM-DD-yyyy");
final FastDateFormat format3 = FastDateFormat.getInstance("MM-DD-yyyy");
assertTrue(format1 != format2); // -- junit 3.8 version -- assertFalse(format1 == format2);
assertSame(format2, format3);
assertEquals("MM/DD/yyyy", format1.getPattern());
assertEquals(TimeZone.getDefault(), format1.getTimeZone());
assertEquals(TimeZone.getDefault(), format2.getTimeZone());
}
@Test
public void test_getInstance_String_TimeZone() {
final Locale realDefaultLocale = Locale.getDefault();
final TimeZone realDefaultZone = TimeZone.getDefault();
try {
Locale.setDefault(Locale.US);
TimeZone.setDefault(TimeZone.getTimeZone("America/New_York"));
final FastDateFormat format1 = FastDateFormat.getInstance("MM/DD/yyyy",
TimeZone.getTimeZone("Atlantic/Reykjavik"));
final FastDateFormat format2 = FastDateFormat.getInstance("MM/DD/yyyy");
final FastDateFormat format3 = FastDateFormat.getInstance("MM/DD/yyyy", TimeZone.getDefault());
final FastDateFormat format4 = FastDateFormat.getInstance("MM/DD/yyyy", TimeZone.getDefault());
final FastDateFormat format5 = FastDateFormat.getInstance("MM-DD-yyyy", TimeZone.getDefault());
final FastDateFormat format6 = FastDateFormat.getInstance("MM-DD-yyyy");
assertTrue(format1 != format2); // -- junit 3.8 version -- assertFalse(format1 == format2);
assertEquals(TimeZone.getTimeZone("Atlantic/Reykjavik"), format1.getTimeZone());
assertEquals(TimeZone.getDefault(), format2.getTimeZone());
assertSame(format3, format4);
assertTrue(format3 != format5); // -- junit 3.8 version -- assertFalse(format3 == format5);
assertTrue(format4 != format6); // -- junit 3.8 version -- assertFalse(format3 == format5);
} finally {
Locale.setDefault(realDefaultLocale);
TimeZone.setDefault(realDefaultZone);
}
}
@Test
public void test_getInstance_String_Locale() {
final Locale realDefaultLocale = Locale.getDefault();
try {
Locale.setDefault(Locale.US);
final FastDateFormat format1 = FastDateFormat.getInstance("MM/DD/yyyy", Locale.GERMANY);
final FastDateFormat format2 = FastDateFormat.getInstance("MM/DD/yyyy");
final FastDateFormat format3 = FastDateFormat.getInstance("MM/DD/yyyy", Locale.GERMANY);
assertTrue(format1 != format2); // -- junit 3.8 version -- assertFalse(format1 == format2);
assertSame(format1, format3);
assertEquals(Locale.GERMANY, format1.getLocale());
} finally {
Locale.setDefault(realDefaultLocale);
}
}
@Test
public void test_changeDefault_Locale_DateInstance() {
final Locale realDefaultLocale = Locale.getDefault();
try {
Locale.setDefault(Locale.US);
final FastDateFormat format1 = FastDateFormat.getDateInstance(FastDateFormat.FULL, Locale.GERMANY);
final FastDateFormat format2 = FastDateFormat.getDateInstance(FastDateFormat.FULL);
Locale.setDefault(Locale.GERMANY);
final FastDateFormat format3 = FastDateFormat.getDateInstance(FastDateFormat.FULL);
assertSame(Locale.GERMANY, format1.getLocale());
assertSame(Locale.US, format2.getLocale());
assertSame(Locale.GERMANY, format3.getLocale());
assertTrue(format1 != format2); // -- junit 3.8 version -- assertFalse(format1 == format2);
assertTrue(format2 != format3);
} finally {
Locale.setDefault(realDefaultLocale);
}
}
@Test
public void test_changeDefault_Locale_DateTimeInstance() {
final Locale realDefaultLocale = Locale.getDefault();
try {
Locale.setDefault(Locale.US);
final FastDateFormat format1 = FastDateFormat.getDateTimeInstance(FastDateFormat.FULL, FastDateFormat.FULL, Locale.GERMANY);
final FastDateFormat format2 = FastDateFormat.getDateTimeInstance(FastDateFormat.FULL, FastDateFormat.FULL);
Locale.setDefault(Locale.GERMANY);
final FastDateFormat format3 = FastDateFormat.getDateTimeInstance(FastDateFormat.FULL, FastDateFormat.FULL);
assertSame(Locale.GERMANY, format1.getLocale());
assertSame(Locale.US, format2.getLocale());
assertSame(Locale.GERMANY, format3.getLocale());
assertTrue(format1 != format2); // -- junit 3.8 version -- assertFalse(format1 == format2);
assertTrue(format2 != format3);
} finally {
Locale.setDefault(realDefaultLocale);
}
}
@Test
public void test_getInstance_String_TimeZone_Locale() {
final Locale realDefaultLocale = Locale.getDefault();
final TimeZone realDefaultZone = TimeZone.getDefault();
try {
Locale.setDefault(Locale.US);
TimeZone.setDefault(TimeZone.getTimeZone("America/New_York"));
final FastDateFormat format1 = FastDateFormat.getInstance("MM/DD/yyyy",
TimeZone.getTimeZone("Atlantic/Reykjavik"), Locale.GERMANY);
final FastDateFormat format2 = FastDateFormat.getInstance("MM/DD/yyyy", Locale.GERMANY);
final FastDateFormat format3 = FastDateFormat.getInstance("MM/DD/yyyy",
TimeZone.getDefault(), Locale.GERMANY);
assertTrue(format1 != format2); // -- junit 3.8 version -- assertNotSame(format1, format2);
assertEquals(TimeZone.getTimeZone("Atlantic/Reykjavik"), format1.getTimeZone());
assertEquals(TimeZone.getDefault(), format2.getTimeZone());
assertEquals(TimeZone.getDefault(), format3.getTimeZone());
assertEquals(Locale.GERMANY, format1.getLocale());
assertEquals(Locale.GERMANY, format2.getLocale());
assertEquals(Locale.GERMANY, format3.getLocale());
} finally {
Locale.setDefault(realDefaultLocale);
TimeZone.setDefault(realDefaultZone);
}
}
@Test
public void testCheckDefaults() {
final FastDateFormat format = FastDateFormat.getInstance();
final FastDateFormat medium = FastDateFormat.getDateTimeInstance(FastDateFormat.SHORT, FastDateFormat.SHORT);
assertEquals(medium, format);
final SimpleDateFormat sdf = new SimpleDateFormat();
assertEquals(sdf.toPattern(), format.getPattern());
assertEquals(Locale.getDefault(), format.getLocale());
assertEquals(TimeZone.getDefault(), format.getTimeZone());
}
@Test
public void testCheckDifferingStyles() {
final FastDateFormat shortShort = FastDateFormat.getDateTimeInstance(FastDateFormat.SHORT, FastDateFormat.SHORT, Locale.US);
final FastDateFormat shortLong = FastDateFormat.getDateTimeInstance(FastDateFormat.SHORT, FastDateFormat.LONG, Locale.US);
final FastDateFormat longShort = FastDateFormat.getDateTimeInstance(FastDateFormat.LONG, FastDateFormat.SHORT, Locale.US);
final FastDateFormat longLong = FastDateFormat.getDateTimeInstance(FastDateFormat.LONG, FastDateFormat.LONG, Locale.US);
assertFalse(shortShort.equals(shortLong));
assertFalse(shortShort.equals(longShort));
assertFalse(shortShort.equals(longLong));
assertFalse(shortLong.equals(longShort));
assertFalse(shortLong.equals(longLong));
assertFalse(longShort.equals(longLong));
}
@Test
public void testDateDefaults() {
assertEquals(FastDateFormat.getDateInstance(FastDateFormat.LONG, Locale.CANADA),
FastDateFormat.getDateInstance(FastDateFormat.LONG, TimeZone.getDefault(), Locale.CANADA));
assertEquals(FastDateFormat.getDateInstance(FastDateFormat.LONG, TimeZone.getTimeZone("America/New_York")),
FastDateFormat.getDateInstance(FastDateFormat.LONG, TimeZone.getTimeZone("America/New_York"), Locale.getDefault()));
assertEquals(FastDateFormat.getDateInstance(FastDateFormat.LONG),
FastDateFormat.getDateInstance(FastDateFormat.LONG, TimeZone.getDefault(), Locale.getDefault()));
}
@Test
public void testTimeDefaults() {
assertEquals(FastDateFormat.getTimeInstance(FastDateFormat.LONG, Locale.CANADA),
FastDateFormat.getTimeInstance(FastDateFormat.LONG, TimeZone.getDefault(), Locale.CANADA));
assertEquals(FastDateFormat.getTimeInstance(FastDateFormat.LONG, TimeZone.getTimeZone("America/New_York")),
FastDateFormat.getTimeInstance(FastDateFormat.LONG, TimeZone.getTimeZone("America/New_York"), Locale.getDefault()));
assertEquals(FastDateFormat.getTimeInstance(FastDateFormat.LONG),
FastDateFormat.getTimeInstance(FastDateFormat.LONG, TimeZone.getDefault(), Locale.getDefault()));
}
@Test
public void testTimeDateDefaults() {
assertEquals(FastDateFormat.getDateTimeInstance(FastDateFormat.LONG, FastDateFormat.MEDIUM, Locale.CANADA),
FastDateFormat.getDateTimeInstance(FastDateFormat.LONG, FastDateFormat.MEDIUM, TimeZone.getDefault(), Locale.CANADA));
assertEquals(FastDateFormat.getDateTimeInstance(FastDateFormat.LONG, FastDateFormat.MEDIUM, TimeZone.getTimeZone("America/New_York")),
FastDateFormat.getDateTimeInstance(FastDateFormat.LONG, FastDateFormat.MEDIUM, TimeZone.getTimeZone("America/New_York"), Locale.getDefault()));
assertEquals(FastDateFormat.getDateTimeInstance(FastDateFormat.LONG, FastDateFormat.MEDIUM),
FastDateFormat.getDateTimeInstance(FastDateFormat.LONG, FastDateFormat.MEDIUM, TimeZone.getDefault(), Locale.getDefault()));
}
@Test
public void testParseSync() throws InterruptedException {
final String pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS Z";
final FastDateFormat formatter= FastDateFormat.getInstance(pattern);
final long sdfTime= measureTime(formatter, new SimpleDateFormat(pattern) {
private static final long serialVersionUID = 1L; // because SimpleDateFormat is serializable
@Override
public Object parseObject(final String formattedDate) throws ParseException {
synchronized(this) {
return super.parse(formattedDate);
}
}
});
final long fdfTime= measureTime(formatter, FastDateFormat.getInstance(pattern));
final String times= ">>FastDateFormatTest: FastDateParser:"+fdfTime+" SimpleDateFormat:"+sdfTime;
System.out.println(times);
}
final static private int NTHREADS= 10;
final static private int NROUNDS= 10000;
private long measureTime(final Format formatter, final Format parser) throws InterruptedException {
final ExecutorService pool = Executors.newFixedThreadPool(NTHREADS);
final AtomicInteger failures= new AtomicInteger(0);
final AtomicLong totalElapsed= new AtomicLong(0);
for(int i= 0; i<NTHREADS; ++i) {
pool.submit(new Runnable() {
@Override
public void run() {
for(int j= 0; j<NROUNDS; ++j) {
try {
final Date date= new Date();
final String formattedDate= formatter.format(date);
final long start= System.currentTimeMillis();
final Object pd= parser.parseObject(formattedDate);
totalElapsed.addAndGet(System.currentTimeMillis()-start);
if(!date.equals(pd)) {
failures.incrementAndGet();
}
} catch (final Exception e) {
failures.incrementAndGet();
e.printStackTrace();
}
}
}
});
}
pool.shutdown();
if(!pool.awaitTermination(20, TimeUnit.SECONDS)) {
pool.shutdownNow();
fail("did not complete tasks");
}
assertEquals(0, failures.get());
return totalElapsed.get();
}
}