package jp.sourceforge.glad.calendar.util;

import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.TimeZone;

import junit.framework.TestCase;

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

    public void testUTC() {
        ISOTimeZone zone = ISOTimeZone.getInstance(0);
        assertEquals("Z", zone.getID());
        try {
            zone.setID("Hoge");
            fail();
        } catch (UnsupportedOperationException e) {}
        
        assertEquals(0, zone.getOffset(
                GregorianCalendar.AD, 2009, 1, 23, Calendar.FRIDAY,
                ((12 * 60 + 23) * 60 + 34) * 1000 + 123));
        assertEquals(0, zone.getOffset(new Date().getTime()));
        assertEquals(0, zone.getRawOffset());
        try {
            zone.setRawOffset(1234567);
            fail();
        } catch (UnsupportedOperationException e) {}
        
        assertEquals("Z", zone.getDisplayName());
        assertEquals("Z", zone.getDisplayName(Locale.JAPAN));
        assertEquals("Z", zone.getDisplayName(false, TimeZone.SHORT));
        assertEquals("Z", zone.getDisplayName(true, TimeZone.LONG, Locale.US));
        
        assertEquals(0, zone.getDSTSavings());
        assertFalse(zone.useDaylightTime());
        assertFalse(zone.inDaylightTime(new Date()));
        
        assertTrue(zone.hasSameRules(zone));
        assertTrue(zone.hasSameRules(TimeZone.getTimeZone("GMT")));
        assertFalse(zone.hasSameRules(TimeZone.getTimeZone("Asia/Tokyo")));
        
        ISOTimeZone clone = zone.clone();
        assertNotSame(zone, clone);
        assertEquals(zone.getID(), clone.getID());
        assertEquals(zone.getRawOffset(), clone.getRawOffset());
        
        assertSame(zone, ISOTimeZone.getInstance("UTC"));
        assertSame(zone, ISOTimeZone.getInstance("UTC", 1234567));
    }

    public void testJST() {
        ISOTimeZone zone = ISOTimeZone.getInstance("Asia/Tokyo");
        assertEquals("+09:00", zone.getID());
        try {
            zone.setID("Hoge");
            fail();
        } catch (UnsupportedOperationException e) {}
        
        int offset = 9 * 60 * 60 * 1000;
        assertEquals(offset, zone.getOffset(
                GregorianCalendar.AD, 2009, 1, 23, Calendar.FRIDAY,
                ((12 * 60 + 23) * 60 + 34) * 1000 + 123));
        assertEquals(offset, zone.getOffset(new Date().getTime()));
        assertEquals(offset, zone.getRawOffset());
        try {
            zone.setRawOffset(1234567);
            fail();
        } catch (UnsupportedOperationException e) {}
        
        assertEquals("+09:00", zone.getDisplayName());
        assertEquals("+09:00", zone.getDisplayName(Locale.JAPAN));
        assertEquals("+0900", zone.getDisplayName(false, TimeZone.SHORT));
        assertEquals("+09:00", zone.getDisplayName(true, TimeZone.LONG, Locale.US));
        
        assertEquals(0, zone.getDSTSavings());
        assertFalse(zone.useDaylightTime());
        assertFalse(zone.inDaylightTime(new Date()));
        
        assertTrue(zone.hasSameRules(zone));
        assertTrue(zone.hasSameRules(TimeZone.getTimeZone("JST")));
        ISOTimeZone clone = zone.clone();
        
        assertNotSame(zone, clone);
        assertEquals(zone.getID(), clone.getID());
        assertEquals(zone.getRawOffset(), clone.getRawOffset());
        
        assertSame(zone, ISOTimeZone.getInstance(offset));
    }

    public void testSeveralIDs() {
        checkID("+14:00", +1, 14,  0);  // offset の最大値
        checkID("+12:45", +1, 12, 45);
        checkID("+09:30", +1,  9, 30);  // オーストラリア中部標準時
        checkID("+00:20", +1,  0, 20);  // オランダ
        checkID("-04:00", -1,  4,  0);  // 太平洋標準時
        checkID("-12:00", -1, 12,  0);  // offset の最小値
    }

    static void checkID(String id, int signum, int hours, int minutes) {
        assertEquals(id, ISOTimeZone.getInstance(
                signum * (hours * 60 + minutes) * 60 * 1000).getID());
    }

}
