/* * Copyright 2001-2005 Stephen Colebourne * * Licensed 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.joda.time.tz; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.StringTokenizer; import java.util.NoSuchElementException; import junit.framework.TestCase; import junit.framework.TestSuite; import org.joda.time.DateTime; import org.joda.time.DateTimeZone; import org.joda.time.tz.ZoneInfoCompiler.DateTimeOfYear; /** * Test cases for ZoneInfoCompiler. * * @author Brian S O'Neill */ public class TestCompiler extends TestCase { public static void main(String[] args) { junit.textui.TestRunner.run(suite()); } public static TestSuite suite() { return new TestSuite(TestCompiler.class); } static final String AMERICA_LOS_ANGELES_FILE = "# Rules for building just America/Los_Angeles time zone.\n" + "\n" + "Rule US 1918 1919 - Mar lastSun 2:00 1:00 D\n" + "Rule US 1918 1919 - Oct lastSun 2:00 0 S\n" + "Rule US 1942 only - Feb 9 2:00 1:00 W # War\n" + "Rule US 1945 only - Aug 14 23:00u 1:00 P # Peace\n" + "Rule US 1945 only - Sep 30 2:00 0 S\n" + "Rule US 1967 max - Oct lastSun 2:00 0 S\n" + "Rule US 1967 1973 - Apr lastSun 2:00 1:00 D\n" + "Rule US 1974 only - Jan 6 2:00 1:00 D\n" + "Rule US 1975 only - Feb 23 2:00 1:00 D\n" + "Rule US 1976 1986 - Apr lastSun 2:00 1:00 D\n" + "Rule US 1987 max - Apr Sun>=1 2:00 1:00 D\n" + "\n" + "Rule CA 1948 only - Mar 14 2:00 1:00 D\n" + "Rule CA 1949 only - Jan 1 2:00 0 S\n" + "Rule CA 1950 1966 - Apr lastSun 2:00 1:00 D\n" + "Rule CA 1950 1961 - Sep lastSun 2:00 0 S\n" + "Rule CA 1962 1966 - Oct lastSun 2:00 0 S\n" + "\n" + "Zone America/Los_Angeles -7:52:58 - LMT 1883 Nov 18 12:00\n" + " -8:00 US P%sT 1946\n" + " -8:00 CA P%sT 1967\n" + " -8:00 US P%sT"; static final String BROKEN_TIMEZONE_FILE = "# Incomplete Rules for building America/Los_Angeles time zone.\n" + "\n" + "Rule US 1918 1919 - Mar lastSun 2:00 1:00 D\n" + "Rule \n" ; // this line is intentionally incomplete static final String BROKEN_TIMEZONE_FILE_2 = "# Incomplete Zone for building America/Los_Angeles time zone.\n" + "\n" + "Rule CA 1948 only - Mar 14 2:00 1:00 D\n" + "Rule CA 1949 only - Jan 1 2:00 0 S\n" + "\n" + "Zone "; // this line is intentionally left incomplete private DateTimeZone originalDateTimeZone = null; public TestCompiler(String name) { super(name); } protected void setUp() throws Exception { originalDateTimeZone = DateTimeZone.getDefault(); DateTimeZone.setDefault(DateTimeZone.UTC); } protected void tearDown() throws Exception { DateTimeZone.setDefault(originalDateTimeZone); } //----------------------------------------------------------------------- public void testDateTimeZoneBuilder() throws Exception { // test multithreading, issue #18 getTestDataTimeZoneBuilder().toDateTimeZone("TestDTZ1", true); final DateTimeZone[] zone = new DateTimeZone[1]; Thread t = new Thread(new Runnable() { public void run() { zone[0] = getTestDataTimeZoneBuilder().toDateTimeZone("TestDTZ2", true); } }); t.start(); t.join(); assertNotNull(zone[0]); } private DateTimeZoneBuilder getTestDataTimeZoneBuilder() { return new DateTimeZoneBuilder() .addCutover(1601, 'w', 1, 1, 1, false, 7200000) .setStandardOffset(3600000) .addRecurringSavings("", 3600000, 1601, Integer.MAX_VALUE, 'w', 3, -1, 1, false, 7200000) .addRecurringSavings("", 0, 1601, Integer.MAX_VALUE, 'w', 10, -1, 1, false, 10800000); } //----------------------------------------------------------------------- public void testCompile() throws Exception { Provider provider = compileAndLoad(AMERICA_LOS_ANGELES_FILE); DateTimeZone tz = provider.getZone("America/Los_Angeles"); assertEquals("America/Los_Angeles", tz.getID()); assertEquals(false, tz.isFixed()); TestBuilder.testForwardTransitions(tz, TestBuilder.AMERICA_LOS_ANGELES_DATA); TestBuilder.testReverseTransitions(tz, TestBuilder.AMERICA_LOS_ANGELES_DATA); } public void testCompileOnBrokenTimeZoneFile() throws Exception { try { Provider provider = compileAndLoad(BROKEN_TIMEZONE_FILE); fail(); } catch(NoSuchElementException nsee) { // This used to be thrown in the Rule constructor fail("NoSuchElementException was thrown; broken timezone file?"); } catch(IllegalArgumentException iae) { assertEquals("Attempting to create a Rule from an incomplete tokenizer", iae.getMessage()); } } public void testCompileOnBrokenTimeZoneFile_2() throws Exception { try { Provider provider = compileAndLoad(BROKEN_TIMEZONE_FILE_2); fail(); } catch (NoSuchElementException nsee) { // This thrown from the Zone constructor fail("NoSuchElementException was thrown; broken timezone file?"); } catch (IllegalArgumentException iae) { assertEquals("Attempting to create a Zone from an incomplete tokenizer", iae.getMessage()); } } private Provider compileAndLoad(String data) throws Exception { File tempDir = createDataFile(data); File destDir = makeTempDir(); ZoneInfoCompiler.main(new String[] { "-src", tempDir.getAbsolutePath(), "-dst", destDir.getAbsolutePath(), "tzdata" }); // Mark all files to be deleted on exit. deleteOnExit(destDir); return new ZoneInfoProvider(destDir); } private File createDataFile(String data) throws IOException { File tempDir = makeTempDir(); File tempFile = new File(tempDir, "tzdata"); tempFile.deleteOnExit(); InputStream in = new ByteArrayInputStream(data.getBytes("UTF-8")); FileOutputStream out = new FileOutputStream(tempFile); byte[] buf = new byte[1000]; int amt; while ((amt = in.read(buf)) > 0) { out.write(buf, 0, amt); } out.close(); in.close(); return tempDir; } private File makeTempDir() { File tempDir = new File(System.getProperty("java.io.tmpdir")); tempDir = new File(tempDir, "joda-test-" + (new java.util.Random().nextInt() & 0xffffff)); tempDir.mkdirs(); tempDir.deleteOnExit(); return tempDir; } private void deleteOnExit(File tempFile) { tempFile.deleteOnExit(); if (tempFile.isDirectory()) { File[] files = tempFile.listFiles(); for (int i=0; i<files.length; i++) { deleteOnExit(files[i]); } } } //----------------------------------------------------------------------- public void test_2400_fromDay() { StringTokenizer st = new StringTokenizer("Apr Sun>=1 24:00"); DateTimeOfYear test = new DateTimeOfYear(st); assertEquals(4, test.iMonthOfYear); // Apr assertEquals(2, test.iDayOfMonth); // 2nd assertEquals(1, test.iDayOfWeek); // Mon assertEquals(0, test.iMillisOfDay); // 00:00 assertEquals(true, test.iAdvanceDayOfWeek); } public void test_2400_last() { StringTokenizer st = new StringTokenizer("Mar lastSun 24:00"); DateTimeOfYear test = new DateTimeOfYear(st); assertEquals(4, test.iMonthOfYear); // Apr assertEquals(1, test.iDayOfMonth); // 1st assertEquals(1, test.iDayOfWeek); // Mon assertEquals(0, test.iMillisOfDay); // 00:00 assertEquals(false, test.iAdvanceDayOfWeek); } public void test_2400_specific_day() { StringTokenizer st = new StringTokenizer("Sep 21 24:00"); DateTimeOfYear test = new DateTimeOfYear(st); assertEquals(9, test.iMonthOfYear); // Sep assertEquals(22, test.iDayOfMonth); // 22st assertEquals(0, test.iDayOfWeek); // Ignored assertEquals(0, test.iMillisOfDay); // 00:00 assertEquals(false, test.iAdvanceDayOfWeek); } public void test_Amman_2003() { DateTimeZone zone = DateTimeZone.forID("Asia/Amman"); DateTime dt = new DateTime(2003, 3, 1, 0, 0, zone); long next = zone.nextTransition(dt.getMillis()); assertEquals(next, new DateTime(2003, 3, 28, 0, 0, DateTimeZone.forOffsetHours(2)).getMillis()); } public void test_Amman_2004() { DateTimeZone zone = DateTimeZone.forID("Asia/Amman"); DateTime dt = new DateTime(2004, 3, 1, 0, 0, zone); long next = zone.nextTransition(dt.getMillis()); assertEquals(next, new DateTime(2004, 3, 26, 0, 0, DateTimeZone.forOffsetHours(2)).getMillis()); } public void test_Amman_2005() { DateTimeZone zone = DateTimeZone.forID("Asia/Amman"); DateTime dt = new DateTime(2005, 3, 1, 0, 0, zone); long next = zone.nextTransition(dt.getMillis()); assertEquals(next, new DateTime(2005, 4, 1, 0, 0, DateTimeZone.forOffsetHours(2)).getMillis()); } public void test_Amman_2006() { DateTimeZone zone = DateTimeZone.forID("Asia/Amman"); DateTime dt = new DateTime(2006, 3, 1, 0, 0, zone); long next = zone.nextTransition(dt.getMillis()); assertEquals(next, new DateTime(2006, 3, 31, 0, 0, DateTimeZone.forOffsetHours(2)).getMillis()); } }