/*
* Copyright (C) 2004, 2005 Joe Walnes.
* Copyright (C) 2006, 2007, 2008 XStream Committers.
* All rights reserved.
*
* The software in this package is published under the terms of the BSD
* style license a copy of which has been included with this distribution in
* the LICENSE.txt file.
*
* Created on 22. February 2004 by Joe Walnes
*/
package com.thoughtworks.xstream.converters.basic;
import com.thoughtworks.xstream.converters.ConversionException;
import com.thoughtworks.xstream.testutil.TimeZoneChanger;
import junit.framework.TestCase;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.TimeZone;
public class DateConverterTest extends TestCase {
private DateConverter converter = new DateConverter();
protected void setUp() throws Exception {
super.setUp();
// Ensure that this test always run as if it were in the IST timezone.
// This prevents failures when running the tests in different zones.
// Note: 'IST' has no relevance - it was just a randomly chosen zone
// without daylight saving.
TimeZoneChanger.change("IST");
}
protected void tearDown() throws Exception {
TimeZoneChanger.reset();
super.tearDown();
}
public void testRetainsDetailDownToMillisecondLevel() {
// setup
Date in = new Date();
// execute
String text = converter.toString(in);
Date out = (Date)converter.fromString(text);
// verify
assertEquals(in, out);
assertEquals(in.toString(), out.toString());
assertEquals(in.getTime(), out.getTime());
}
public void testUnmarshalsOldXStreamDatesThatLackMillisecond() {
Date expected = (Date)converter.fromString("2004-02-22 15:16:04.0 EST");
assertEquals(expected, converter.fromString("2004-02-22 15:16:04.0 EST"));
assertEquals(expected, converter.fromString("2004-02-22 15:16:04 EST"));
assertEquals(expected, converter.fromString("2004-02-22 15:16:04EST"));
TimeZone.setDefault(TimeZone.getTimeZone("EST")); // Need correct local time, no TZ info in string
assertEquals(expected, converter.fromString("2004-02-22 15:16:04.0 PM"));
assertEquals(expected, converter.fromString("2004-02-22 15:16:04PM"));
}
public void testUnmarshalsDatesWithDifferentTimeZones() {
converter = new DateConverter(true); // Needed by JDK 5 running on Codehaus' Bamboo installation
Date expected = (Date)converter.fromString("2004-02-22 15:16:04.0 EST");
assertEquals(expected, converter.fromString("2004-02-22 15:16:04.0 EST"));
assertEquals(expected, converter.fromString("2004-02-22 15:16:04.0 GMT-05:00"));
assertEquals(expected, converter.fromString("2004-02-22 20:16:04.0 UTC"));
assertEquals(expected, converter.fromString("2004-02-23 01:46:04.0 IST"));
assertEquals(expected, converter.fromString("2004-02-23 01:46:04.0 GMT+05:30"));
}
public void testUnmarshalsDateWithDifferentDefaultTimeZones() throws ParseException {
Calendar cal = Calendar.getInstance();
cal.clear();
cal.set(2004, Calendar.FEBRUARY, 23, 1, 46, 4);
Date date = cal.getTime();
String strIST = converter.toString(date);
assertEquals("2004-02-23 01:46:04.0 IST", strIST);
// select arbitrary TZ
TimeZone.setDefault(TimeZone.getTimeZone("EST"));
// compare parsed date with JDK implementation
Date dateRetrieved = (Date)converter.fromString(strIST);
SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.S z");
Date simpleDate = f.parse(strIST);
assertEquals(simpleDate, dateRetrieved);
// DateConverter does not get influenced by change of current TZ ...
TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
dateRetrieved = (Date)converter.fromString(strIST);
assertEquals(simpleDate, dateRetrieved);
// ... as well as the SimpleDateFormat
f = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.S z");
simpleDate = f.parse(strIST);
assertEquals(simpleDate, dateRetrieved);
assertEquals(date, f.parse("2004-02-22 20:16:04.0 UTC"));
// assertEquals(date, simpleDate); off by +03:30 ... but why ??
}
public void testIsThreadSafe() throws InterruptedException {
final List results = Collections.synchronizedList(new ArrayList());
final DateConverter converter = new DateConverter();
final Object monitor = new Object();
final int numberOfCallsPerThread = 20;
final int numberOfThreads = 20;
// spawn some concurrent threads, that hammer the converter
Runnable runnable = new Runnable() {
public void run() {
for (int i = 0; i < numberOfCallsPerThread; i++) {
try {
converter.fromString("2004-02-22 15:16:04.0 EST");
results.add("PASS");
} catch (ConversionException e) {
results.add("FAIL");
} finally {
synchronized (monitor) {
monitor.notifyAll();
}
}
}
}
};
for (int i = 0; i < numberOfThreads; i++) {
new Thread(runnable).start();
}
// wait for all results
while (results.size() < numberOfThreads * numberOfCallsPerThread) {
synchronized (monitor) {
monitor.wait(100);
}
}
assertTrue("Nothing suceeded", results.contains("PASS"));
assertFalse("At least one attempt failed", results.contains("FAIL"));
}
public void testDatesInNonLenientMode() {
String[] dateFormats = new String[] { "yyyyMMdd", "yyyy-MM-dd'T'HH:mm:ss'Z'", "yyyy-MM-dd" };
converter = new DateConverter("yyyy-MM-dd'T'HH:mm:ss.S'Z'", dateFormats);
Date expected = (Date)converter.fromString("2004-02-22T15:16:04.0Z");
assertEquals(expected, converter.fromString("2004-02-22T15:16:04Z"));
}
public void testDatesInLenientMode() {
converter = new DateConverter("yyyy-MM-dd HH:mm:ss.S z", new String[0], true);
Date expected = (Date)converter.fromString("2004-02-22 15:16:04.0 IST");
assertEquals(expected, converter.fromString("2004-02-21 39:16:04.0 IST"));
}
public void testDatesIn70sInTimeZoneGMT() throws ParseException {
final String pattern = "yyyy-MM-dd HH:mm:ss.S z";
final SimpleDateFormat format;
format = new SimpleDateFormat(pattern, Locale.UK);
format.setTimeZone(TimeZone.getTimeZone("GMT"));
final String[] expected = new String[]{
"1970-01-01 11:20:34.0 GMT",
"1971-01-01 11:20:34.0 GMT",
"1972-01-01 11:20:34.0 GMT",
"1973-01-01 11:20:34.0 GMT",
"1974-01-01 11:20:34.0 GMT",
};
final String[] actual = new String[expected.length];
for (int i = 0; i < actual.length; i++ ) {
final String converted = converter.toString(format.parseObject(expected[i]));
// Note, XStream's string representation of the date is in IST
actual[i] = format.format(converter.fromString(converted));
}
assertEquals(Arrays.asList(expected).toString(), Arrays.asList(actual).toString());
}
}