package jp.sourceforge.glad.calendar;

import static jp.sourceforge.glad.calendar.CalendarConsts.*;

import java.sql.Timestamp;
import java.util.Calendar;
import java.util.Locale;
import java.util.TimeZone;

import junit.framework.TestCase;

/**
 * {@link ISOCalendar} の単体テスト。
 * 
 * @author GLAD!!
 */
public class ISOCalendarTest extends TestCase {

    TimeZone defaultTz;

    protected void setUp() throws Exception {
        defaultTz = TimeZone.getDefault();
    }

    protected void tearDown() throws Exception {
        TimeZone.setDefault(defaultTz);
        defaultTz = null;
    }

    /**
     * デフォルトコンストラクタのテスト。
     */
    public void testConstruct() {
        ISOCalendar x = new ISOCalendar();
        assertEquals(defaultTz, x.getTimeZone());
    }

    /**
     * タイムゾーンを引数とした構築のテスト。
     */
    public void testConstruct_TimeZone() {
        ISOCalendar x = new ISOCalendar(UTC);
        assertEquals(UTC, x.getTimeZone());
        
        x = new ISOCalendar(JST);
        assertEquals(JST, x.getTimeZone());
    }

    /**
     * 年月を引数とした構築のテスト。
     */
    public void testConstruct_MD() {
        ISOCalendar x = new ISOCalendar(1, 23);
        assertEquals(1,  x.getMonth());
        assertEquals(23, x.getDay());
        assertEquals(0,  x.getHour());
        assertEquals(0,  x.getMinute());
        assertEquals(0,  x.getSecond());
        assertEquals(0,  x.getMillis());
        assertEquals(defaultTz, x.getTimeZone());
    }

    /**
     * 年月日を引数とした構築のテスト。
     */
    public void testConstruct_YMD() {
        ISOCalendar x = new ISOCalendar(2007, 1, 23);
        assertEquals(2007, x.getYear());
        assertEquals(1,  x.getMonth());
        assertEquals(23, x.getDay());
        assertEquals(CalendarConsts.TUESDAY, x.getDayOfWeek());
        assertEquals(0,  x.getHour());
        assertEquals(0,  x.getMinute());
        assertEquals(0,  x.getSecond());
        assertEquals(0,  x.getMillis());
        assertEquals(defaultTz, x.getTimeZone());
    }

    /**
     * 年月日時分を引数とした構築のテスト。
     */
    public void testConstruct_YMDHM() {
        ISOCalendar x = new ISOCalendar(2007, 1, 23, 12, 34);
        assertEquals(2007, x.getYear());
        assertEquals(1,  x.getMonth());
        assertEquals(23, x.getDay());
        assertEquals(12, x.getHour());
        assertEquals(34, x.getMinute());
        assertEquals(0,  x.getSecond());
        assertEquals(0,  x.getMillis());
        assertEquals(defaultTz, x.getTimeZone());
    }

    /**
     * 年月日時分秒を引数とした構築のテスト。
     */
    public void testConstruct_YMDHMS() {
        ISOCalendar x = new ISOCalendar(2007, 1, 23, 12, 34, 56);
        assertEquals(2007, x.getYear());
        assertEquals(1,  x.getMonth());
        assertEquals(23, x.getDay());
        assertEquals(12, x.getHour());
        assertEquals(34, x.getMinute());
        assertEquals(56, x.getSecond());
        assertEquals(0,  x.getMillis());
        assertEquals(defaultTz, x.getTimeZone());
    }

    /**
     * 年月日時分秒ミリ秒を引数とした構築のテスト。
     */
    public void testConstruct_YMDHMSS() {
        ISOCalendar x = new ISOCalendar(2007, 1, 23, 12, 34, 56, 123);
        assertEquals(2007, x.getYear());
        assertEquals(1,  x.getMonth());
        assertEquals(23, x.getDay());
        assertEquals(12, x.getHour());
        assertEquals(34, x.getMinute());
        assertEquals(56, x.getSecond());
        assertEquals(123, x.getMillis());
        assertEquals(defaultTz, x.getTimeZone());
    }

    /**
     * 1970-01-01T00:00:00Z からのミリ秒を引数とした構築のテスト。
     */
    public void testConstruct_timeInMills() {
        long millis = System.currentTimeMillis();
        ISOCalendar x = new ISOCalendar(millis);
        assertEquals(millis, x.getTimeInMillis());
        assertEquals(defaultTz, x.getTimeZone());
    }

    /**
     * 1970-01-01T00:00:00Z からのミリ秒と
     * タイムゾーンを引数とした構築のテスト。
     */
    public void testConstruct_timeInMills_TimeZone() {
        ISOCalendar x = new ISOCalendar(0L, UTC);
        assertEquals(0L, x.getTimeInMillis());
        assertEquals(UTC, x.getTimeZone());
        assertEquals("1970-01-01T00:00:00.000Z", x.toString());
        
        x = new ISOCalendar(0L, JST);
        assertEquals(0L, x.getTimeInMillis());
        assertEquals(JST, x.getTimeZone());
        assertEquals("1970-01-01T09:00:00.000+09:00", x.toString());
    }

    /**
     * Calendar を引数とした構築のテスト。
     */
    public void testConstruct_Calendar() {
        Calendar calendar = Calendar.getInstance();
        ISOCalendar x = new ISOCalendar(calendar);
        assertTrue(calendar.compareTo(x.toGregorianCalendar()) == 0);
        assertEquals(defaultTz, x.getTimeZone());
    }

    /**
     * java.util.Date を引数とした構築のテスト。
     */
    public void testConstruct_Date() {
        java.util.Date date = new java.util.Date();
        ISOCalendar x = new ISOCalendar(date);
        assertEquals(date, x.toDate());
        assertEquals(defaultTz, x.getTimeZone());
    }

    /**
     * java.sql.Date を引数とした構築のテスト。
     */
    public void testConstruct_sqlDate() {
        java.sql.Date date = java.sql.Date.valueOf("2007-01-23");
        ISOCalendar x = new ISOCalendar(date);
        assertEquals(date, x.toSqlDate());
        assertEquals(defaultTz, x.getTimeZone());
        assertEquals("2007-01-23T00:00:00.000", x.formatDateTime());
    }

    /**
     * java.sql.Time を引数とした構築のテスト。
     */
    public void testConstruct_sqlTime() {
        java.sql.Time time = java.sql.Time.valueOf("12:34:56");
        ISOCalendar x = new ISOCalendar(time);
        assertEquals(time, x.toSqlTime());
        assertEquals(defaultTz, x.getTimeZone());
        assertEquals("1970-01-01T12:34:56.000", x.formatDateTime());
    }

    /**
     * java.sql.Timestamp を引数とした構築のテスト。
     */
    public void testConstruct_Timestamp() {
        Timestamp timestamp = Timestamp.valueOf(
                "2007-01-23 12:34:56.123456789");
        ISOCalendar x = new ISOCalendar(timestamp);
        //assertEquals(timestamp, x.getTimestamp());
        assertEquals(defaultTz, x.getTimeZone());
        assertEquals("2007-01-23T12:34:56.123", x.formatDateTime());
    }

    /**
     * コピーコンストラクタのテスト。
     */
    public void testConstruct_ISOCalendar() {
        ISOCalendar x = new ISOCalendar();
        ISOCalendar copy = new ISOCalendar(x);
        assertNotSame(x, copy);
        assertEquals(x.toGregorianCalendar(), copy.toGregorianCalendar());
    }

    public void testDayOfWeekText() {
        ISOCalendar x = new ISOCalendar(2009, 1, 23, 12, 34, 56, 123);
        assertEquals("金曜日", x.getDayOfWeekText());
        assertEquals("Friday", x.getDayOfWeekText(Locale.US));
        assertEquals("金", x.getDayOfWeekShortText());
        assertEquals("Fri", x.getDayOfWeekShortText(Locale.US));
    }

    public void testToSqlDate() {
        ISOCalendar calendar = new ISOCalendar();
        long timeInMillis = calendar.getTimeInMillis();
        java.sql.Date date = calendar.toSqlDate();
        // 元の ISOCalendar が変更されていないこと。
        assertEquals(timeInMillis, calendar.getTimeInMillis());
        ISOCalendar actual = new ISOCalendar(date.getTime());
        assertEquals(calendar.getYear(), actual.getYear());
        assertEquals(calendar.getMonth(), actual.getMonth());
        assertEquals(calendar.getDay(), actual.getDay());
        assertEquals(0, actual.getHour());
        assertEquals(0, actual.getMinute());
        assertEquals(0, actual.getSecond());
        assertEquals(0, actual.getMillis());
    }

    public void testToSqlTime() {
        ISOCalendar calendar = new ISOCalendar();
        long timeInMillis = calendar.getTimeInMillis();
        java.sql.Time time = calendar.toSqlTime();
        // 元の ISOCalendar が変更されていないこと。
        assertEquals(timeInMillis, calendar.getTimeInMillis());
        ISOCalendar actual = new ISOCalendar(time.getTime());
        assertEquals(1970, actual.getYear());
        assertEquals(1, actual.getMonth());
        assertEquals(1, actual.getDay());
        assertEquals(calendar.getHour(), actual.getHour());
        assertEquals(calendar.getMinute(), actual.getMinute());
        assertEquals(calendar.getSecond(), actual.getSecond());
    }

    public void testFormat() {
        ISOCalendar calendar = new ISOCalendar(
                2009, 1, 23, 12, 34, 56, 123, CalendarConsts.JST);
        assertEquals("2009-01-23", calendar.formatDate());
        assertEquals("12:34:56.123", calendar.formatTime());
        assertEquals("12:34:56.123+09:00", calendar.formatTime(true));
        assertEquals("2009-01-23T12:34:56.123",
                calendar.formatDateTime());
        assertEquals("2009-01-23T12:34:56.123+09:00",
                calendar.formatDateTime(true));
    }

}
