package w3cdtf;

import java.text.DateFormat;
import java.text.ParseException;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;

import junit.framework.TestCase;

/** <code>W3cdtfDateFormat</code> ユニットテストクラス. */
public class W3cdtfDateFormatTest extends TestCase {

	/** テスト用時刻 <code>1248320096789L = 2009-07-23T12:34:56.789+09:00 = 2009-07-23T03:34:56.789Z</code> */
	private static final long time = 1248320096789L;

	@Override
	protected void setUp() throws Exception {
		super.setUp();
	}

	@Override
	protected void tearDown() throws Exception {
		super.tearDown();
	}

	private Date toDate(int year, int month, int date, int hour, int minute, int second, int millis, int tzh) {
		Calendar calendar = Calendar.getInstance();
		calendar.clear();
		calendar.set(Calendar.YEAR, year);
		calendar.set(Calendar.MONTH, month - 1);
		calendar.set(Calendar.DAY_OF_MONTH, date);
		calendar.set(Calendar.HOUR_OF_DAY, hour);
		calendar.set(Calendar.MINUTE, minute);
		calendar.set(Calendar.SECOND, second);
		calendar.set(Calendar.MILLISECOND, millis);
		calendar.set(Calendar.ZONE_OFFSET, tzh * 60 * 60000);
		return calendar.getTime();
	}

	/**
	 * フォーマット.
	 * <code>null</code>を指定した場合、NullPointerException となる
	 * @throws Exception 例外
	 */
	public void testFormat_setNull() throws Exception {
		DateFormat formater = new W3cdtfDateFormat();
		try {
			formater.format(null);
			fail("例外にならなかった");
		} catch (NullPointerException e) {
			// NullPointerException ならOK
		}
	}

	/**
	 * フォーマット.
	 * @throws Exception 例外
	 */
	public void testFormat() throws Exception {
		DateFormat formater = new W3cdtfDateFormat();
		assertEquals("2009-07-23T12:34:56.789+09:00", formater.format(new Date(time)));
	}

	/**
	 * フォーマット.
	 * @throws Exception 例外
	 */
	public void testFormat_UTC() throws Exception {
		DateFormat formater = new W3cdtfDateFormat();
		formater.setTimeZone(TimeZone.getTimeZone("GMT"));
		assertEquals("2009-07-23T03:34:56.789Z", formater.format(new Date(time)));
	}

	/**
	 * フォーマット.
	 * パターン：年月日および時分秒および小数部分
	 * @throws Exception 例外
	 */
	public void testFormat_MILLISECOND() throws Exception {
		DateFormat formater = new W3cdtfDateFormat(W3cdtfDateFormat.MILLISECOND);
		assertEquals("2009-07-23T12:34:56.789+09:00", formater.format(new Date(time)));
	}

	/**
	 * フォーマット.
	 * パターン：年月日および時分秒
	 * @throws Exception 例外
	 */
	public void testFormat_SECOND() throws Exception {
		DateFormat formater = new W3cdtfDateFormat(W3cdtfDateFormat.SECOND);
		assertEquals("2009-07-23T12:34:56+09:00", formater.format(new Date(time)));
	}

	/**
	 * フォーマット.
	 * パターン：年月日および時分
	 * @throws Exception 例外
	 */
	public void testFormat_MINUTE() throws Exception {
		DateFormat formater = new W3cdtfDateFormat(W3cdtfDateFormat.MINUTE);
		assertEquals("2009-07-23T12:34+09:00", formater.format(new Date(time)));
	}

	/**
	 * フォーマット.
	 * パターン：年月日
	 * @throws Exception 例外
	 */
	public void testFormat_DATE() throws Exception {
		DateFormat formater = new W3cdtfDateFormat(W3cdtfDateFormat.DATE);
		assertEquals("2009-07-23", formater.format(new Date(time)));
	}

	/**
	 * フォーマット.
	 * パターン：年月
	 * @throws Exception 例外
	 */
	public void testFormat_MONTH() throws Exception {
		DateFormat formater = new W3cdtfDateFormat(W3cdtfDateFormat.MONTH);
		assertEquals("2009-07", formater.format(new Date(time)));
	}

	/**
	 * フォーマット.
	 * パターン：年
	 * @throws Exception 例外
	 */
	public void testFormat_YEAR() throws Exception {
		DateFormat formater = new W3cdtfDateFormat(W3cdtfDateFormat.YEAR);
		assertEquals("2009", formater.format(new Date(time)));
	}

	/**
	 * フォーマット.
	 * パターン：年月日および時分秒および小数部分 タイムゾーン無し
	 * @throws Exception 例外
	 */
	public void testFormat_MILLISECOND_OmitTZ() throws Exception {
		DateFormat formater = new W3cdtfDateFormat(W3cdtfDateFormat.MILLISECOND, true);
		assertEquals("2009-07-23T12:34:56.789", formater.format(new Date(time)));
	}

	/**
	 * フォーマット.
	 * パターン：年月日および時分秒 タイムゾーン無し
	 * @throws Exception 例外
	 */
	public void testFormat_SECOND_OmitTZ() throws Exception {
		DateFormat formater = new W3cdtfDateFormat(W3cdtfDateFormat.SECOND, true);
		assertEquals("2009-07-23T12:34:56", formater.format(new Date(time)));
	}

	/**
	 * フォーマット.
	 * パターン：年月日および時分 タイムゾーン無し
	 * @throws Exception 例外
	 */
	public void testFormat_MINUTE_OmitTZ() throws Exception {
		DateFormat formater = new W3cdtfDateFormat(W3cdtfDateFormat.MINUTE, true);
		assertEquals("2009-07-23T12:34", formater.format(new Date(time)));
	}

	/**
	 * パース.
	 * <code>null</code>を指定した場合、ParseException となる
	 * @throws Exception 例外
	 */
	public void testParse_setNull() throws Exception {
		DateFormat formater = new W3cdtfDateFormat();
		try {
			formater.parse(null);
			fail("例外にならなかった");
		} catch (ParseException e) {
			// ParseException ならOK
		} catch (NullPointerException e) {
			throw e;
		}
	}

	/**
	 * パース.
	 * 空文字列を指定した場合、ParseException となる
	 * @throws Exception 例外
	 */
	public void testParse_setEmpty() throws Exception {
		DateFormat formater = new W3cdtfDateFormat();
		try {
			formater.parse("");
			fail("例外にならなかった");
		} catch (ParseException e) {
			// ParseException ならOK
		}
	}

	/**
	 * パース.
	 * 空文字列を指定した場合、ParseException となる
	 * @throws Exception 例外
	 */
	public void testParse_setErrorString() throws Exception {
		DateFormat formater = new W3cdtfDateFormat();
		try {
			formater.parse("2009/07/23 12:34:56.789+09");
			fail("例外にならなかった");
		} catch (ParseException e) {
			// ParseException ならOK
		}
	}

	/**
	 * パース.
	 * @throws Exception 例外
	 */
	public void testParse() throws Exception {
		DateFormat formater = new W3cdtfDateFormat();
		assertEquals(new Date(time), formater.parse("2009-07-23T12:34:56.789+09:00"));
	}

	/**
	 * パース.
	 * @throws Exception 例外
	 */
	public void testParse_UTC() throws Exception {
		DateFormat formater = new W3cdtfDateFormat();
		assertEquals(new Date(time), formater.parse("2009-07-23T03:34:56.789Z"));
	}

	/**
	 * パース.
	 * @throws Exception 例外
	 */
	public void testParse1() throws Exception {
		DateFormat formater = new W3cdtfDateFormat();
		assertEquals(new Date(time), formater.parse("2009/07/23T12:34:56.789+09:00"));
	}

	/**
	 * パース.
	 * @throws Exception 例外
	 */
	public void testParse2() throws Exception {
		DateFormat formater = new W3cdtfDateFormat();
		assertEquals(new Date(time), formater.parse("2009.07.23T12:34:56.789+09:00"));
	}

	/**
	 * パース.
	 * @throws Exception 例外
	 */
	public void testParse3() throws Exception {
		DateFormat formater = new W3cdtfDateFormat();
		assertEquals(new Date(time), formater.parse("2009-07-23 12:34:56.789+09:00"));
	}

	/**
	 * パース.
	 * パターン：年月日および時分秒および小数部分
	 * @throws Exception 例外
	 */
	public void testParse_MILLISECOND() throws Exception {
		DateFormat formater = new W3cdtfDateFormat(W3cdtfDateFormat.MILLISECOND);
		assertEquals(toDate(2009, 7, 23, 12, 34, 56, 789, 8), formater.parse("2009-07-23T12:34:56.789+08:00"));
	}

	/**
	 * パース.
	 * パターン：年月日および時分秒
	 * @throws Exception 例外
	 */
	public void testParse_SECOND() throws Exception {
		DateFormat formater = new W3cdtfDateFormat(W3cdtfDateFormat.SECOND);
		assertEquals(toDate(2009, 7, 23, 12, 34, 56, 0, 8), formater.parse("2009-07-23T12:34:56+08:00"));
	}

	/**
	 * パース.
	 * パターン：年月日および時分
	 * @throws Exception 例外
	 */
	public void testParse_MINUTE() throws Exception {
		DateFormat formater = new W3cdtfDateFormat(W3cdtfDateFormat.MINUTE);
		assertEquals(toDate(2009, 7, 23, 12, 34, 0, 0, 8), formater.parse("2009-07-23T12:34+08:00"));
	}

	/**
	 * パース.
	 * パターン：年月日
	 * @throws Exception 例外
	 */
	public void testParse_DATE() throws Exception {
		DateFormat formater = new W3cdtfDateFormat(W3cdtfDateFormat.DATE);
		assertEquals(toDate(2009, 7, 23, 0, 0, 0, 0, 9), formater.parse("2009-07-23"));
	}

	/**
	 * パース.
	 * パターン：年月
	 * @throws Exception 例外
	 */
	public void testParse_MONTH() throws Exception {
		DateFormat formater = new W3cdtfDateFormat(W3cdtfDateFormat.MONTH);
		assertEquals(toDate(2009, 7, 0, 0, 0, 0, 0, 9), formater.parse("2009-07"));
	}

	/**
	 * パース.
	 * パターン：年
	 * @throws Exception 例外
	 */
	public void testParse_YEAR() throws Exception {
		DateFormat formater = new W3cdtfDateFormat(W3cdtfDateFormat.YEAR);
		assertEquals(toDate(2009, 1, 0, 0, 0, 0, 0, 9), formater.parse("2009"));
	}

	/**
	 * パース.
	 * パターン：年月日および時分秒および小数部分 タイムゾーン無し
	 * @throws Exception 例外
	 */
	public void testParse_MILLISECOND_OmitTZ() throws Exception {
		DateFormat formater = new W3cdtfDateFormat(W3cdtfDateFormat.MILLISECOND, true);
		assertEquals(toDate(2009, 7, 23, 12, 34, 56, 789, 9), formater.parse("2009-07-23T12:34:56.789"));
	}

	/**
	 * パース.
	 * パターン：年月日および時分秒 タイムゾーン無し
	 * @throws Exception 例外
	 */
	public void testParse_SECOND_OmitTZ() throws Exception {
		DateFormat formater = new W3cdtfDateFormat(W3cdtfDateFormat.SECOND, true);
		assertEquals(toDate(2009, 7, 23, 12, 34, 56, 0, 9), formater.parse("2009-07-23T12:34:56"));
	}

	/**
	 * パース.
	 * パターン：年月日および時分 タイムゾーン無し
	 * @throws Exception 例外
	 */
	public void testParse_MINUTE_OmitTZ() throws Exception {
		DateFormat formater = new W3cdtfDateFormat(W3cdtfDateFormat.MINUTE, true);
		assertEquals(toDate(2009, 7, 23, 12, 34, 0, 0, 9), formater.parse("2009-07-23T12:34"));
	}

}
