diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 55e8c0c2b..c4491ee0e 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -46,6 +46,7 @@ The type attribute can be add,update,fix,remove. + TimeZone.getTimeZone() in FastDateParser causes resource contention (PR #296.) StackOverflowError on TypeUtils.toString(...) for a generic return type of Enum.valueOf Remove deprecation from RandomStringUtils ConstructorUtils.invokeConstructor(Class, Object...) regression diff --git a/src/main/java/org/apache/commons/lang3/time/DateFormatUtils.java b/src/main/java/org/apache/commons/lang3/time/DateFormatUtils.java index 09d2c521c..b353e0db0 100644 --- a/src/main/java/org/apache/commons/lang3/time/DateFormatUtils.java +++ b/src/main/java/org/apache/commons/lang3/time/DateFormatUtils.java @@ -38,7 +38,7 @@ public class DateFormatUtils { * The UTC time zone (often referred to as GMT). * This is private as it is mutable. */ - private static final TimeZone UTC_TIME_ZONE = TimeZone.getTimeZone("GMT"); + private static final TimeZone UTC_TIME_ZONE = FastTimeZone.getGmtTimeZone(); /** * ISO 8601 formatter for date-time without time zone. diff --git a/src/main/java/org/apache/commons/lang3/time/FastDateParser.java b/src/main/java/org/apache/commons/lang3/time/FastDateParser.java index 3c8fe8c72..33815588e 100644 --- a/src/main/java/org/apache/commons/lang3/time/FastDateParser.java +++ b/src/main/java/org/apache/commons/lang3/time/FastDateParser.java @@ -888,11 +888,8 @@ public class FastDateParser implements DateParser, Serializable { */ @Override void setCalendar(final FastDateParser parser, final Calendar cal, final String timeZone) { - if (timeZone.charAt(0) == '+' || timeZone.charAt(0) == '-') { - final TimeZone tz = TimeZone.getTimeZone(TimeZones.GMT_ID + timeZone); - cal.setTimeZone(tz); - } else if (timeZone.regionMatches(true, 0, TimeZones.GMT_ID, 0, 3)) { - final TimeZone tz = TimeZone.getTimeZone(timeZone.toUpperCase(Locale.ROOT)); + TimeZone tz = FastTimeZone.getGmtTimeZone(timeZone); + if (tz != null) { cal.setTimeZone(tz); } else { final TzInfo tzInfo = tzNames.get(timeZone.toLowerCase(locale)); @@ -918,11 +915,7 @@ public class FastDateParser implements DateParser, Serializable { */ @Override void setCalendar(final FastDateParser parser, final Calendar cal, final String value) { - if (value.equals("Z")) { - cal.setTimeZone(TimeZone.getTimeZone(TimeZones.GMT_ID)); - } else { - cal.setTimeZone(TimeZone.getTimeZone(TimeZones.GMT_ID + value)); - } + cal.setTimeZone(FastTimeZone.getGmtTimeZone(value)); } private static final Strategy ISO_8601_1_STRATEGY = new ISO8601TimeZoneStrategy("(Z|(?:[+-]\\d{2}))"); diff --git a/src/main/java/org/apache/commons/lang3/time/FastTimeZone.java b/src/main/java/org/apache/commons/lang3/time/FastTimeZone.java new file mode 100644 index 000000000..3962479f4 --- /dev/null +++ b/src/main/java/org/apache/commons/lang3/time/FastTimeZone.java @@ -0,0 +1,95 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.commons.lang3.time; + +import java.util.TimeZone; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Faster methods to produce custom time zones. + * + * @since 3.7 + */ +public class FastTimeZone { + + private static final TimeZone GREENWICH = new GmtTimeZone(false, 0, 0); + + // do not instantiate + private FastTimeZone() { + } + + /** + * Get the GMT TimeZone. + * @return A TimeZone with a raw offset of zero. + */ + public static TimeZone getGmtTimeZone() { + return GREENWICH; + } + + /** + * Get a TimeZone, looking first for GMT custom ids, then falling back to Olson ids. + * A GMT custom id can be 'Z', or 'UTC', or has an optional prefix of GMT, + * followed by sign, hours digit(s), optional colon(':'), and optional minutes digits. + * i.e. [GMT] (+|-) Hours [[:] Minutes] + * + * @param id A GMT custom id (or Olson id + * @return A timezone + */ + public static TimeZone getTimeZone(String id) { + TimeZone tz = getGmtTimeZone(id); + if (tz != null) { + return tz; + } + return TimeZone.getTimeZone(id); + } + + private static final Pattern GMT_PATTERN = Pattern.compile("^(?:(?i)GMT)?([+-])?(\\d\\d?)?(:?(\\d\\d?))?$"); + + /** + * Get a TimeZone with GMT offsets. A GMT offset must be either 'Z', or 'UTC', or match + * (GMT)? hh?(:?mm?)?, where h and m are digits representing hours and minutes. + * + * @param pattern The GMT offset + * @return A TimeZone with offset from GMT or null, if pattern does not match. + */ + public static TimeZone getGmtTimeZone(String pattern) { + if ("Z".equals(pattern) || "UTC".equals(pattern)) { + return GREENWICH; + } + + Matcher m = GMT_PATTERN.matcher(pattern); + if (m.matches()) { + int hours = parseInt(m.group(2)); + int minutes = parseInt(m.group(4)); + if (hours == 0 && minutes == 0) { + return GREENWICH; + } + return new GmtTimeZone(parseSign(m.group(1)), hours, minutes); + } + return null; + } + + private static int parseInt(String group) { + return group != null ? Integer.parseInt(group) : 0; + } + + private static boolean parseSign(String group) { + return group != null && group.charAt(0) == '-'; + } + +} diff --git a/src/main/java/org/apache/commons/lang3/time/GmtTimeZone.java b/src/main/java/org/apache/commons/lang3/time/GmtTimeZone.java new file mode 100644 index 000000000..1a7462b3d --- /dev/null +++ b/src/main/java/org/apache/commons/lang3/time/GmtTimeZone.java @@ -0,0 +1,106 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.commons.lang3.time; + +import java.util.Date; +import java.util.TimeZone; + +/** + * Custom timezone that contains offset from GMT. + * + * @since 3.7 + */ +class GmtTimeZone extends TimeZone { + + private static final int MILLISECONDS_PER_MINUTE = 60 * 1000; + private static final int MINUTES_PER_HOUR = 60; + private static final int HOURS_PER_DAY = 24; + + // Serializable! + static final long serialVersionUID = 1L; + + private final int offset; + private final String zoneId; + + GmtTimeZone(boolean negate, int hours, int minutes) { + if (hours >= HOURS_PER_DAY) { + throw new IllegalArgumentException(hours + " hours out of range"); + } + if (minutes >= MINUTES_PER_HOUR) { + throw new IllegalArgumentException(minutes + " minutes out of range"); + } + int milliseconds = (minutes + (hours * MINUTES_PER_HOUR)) * MILLISECONDS_PER_MINUTE; + offset = negate ? -milliseconds : milliseconds; + zoneId = twoDigits( + twoDigits(new StringBuilder(9).append("GMT").append(negate ? '-' : '+'), hours) + .append(':'), minutes).toString(); + + } + + private static StringBuilder twoDigits(StringBuilder sb, int n) { + return sb.append((char) ('0' + (n / 10))).append((char) ('0' + (n % 10))); + } + + @Override + public int getOffset(int era, int year, int month, int day, int dayOfWeek, int milliseconds) { + return offset; + } + + @Override + public void setRawOffset(int offsetMillis) { + throw new UnsupportedOperationException(); + } + + @Override + public int getRawOffset() { + return offset; + } + + @Override + public String getID() { + return zoneId; + } + + @Override + public boolean useDaylightTime() { + return false; + } + + @Override + public boolean inDaylightTime(Date date) { + return false; + } + + @Override + public String toString() { + return "[GmtTimeZone id=\"" + zoneId + "\",offset=" + offset + ']'; + } + + @Override + public int hashCode() { + return offset; + } + + @Override + public boolean equals(Object other) { + if (!(other instanceof GmtTimeZone)) { + return false; + } else { + return zoneId == ((GmtTimeZone) other).zoneId; + } + } +} diff --git a/src/main/java/org/apache/commons/lang3/time/TimeZones.java b/src/main/java/org/apache/commons/lang3/time/TimeZones.java index 634a9e321..5a7569042 100644 --- a/src/main/java/org/apache/commons/lang3/time/TimeZones.java +++ b/src/main/java/org/apache/commons/lang3/time/TimeZones.java @@ -24,6 +24,10 @@ package org.apache.commons.lang3.time; */ public class TimeZones { + // do not instantiate + private TimeZones() { + } + /** * A public version of {@link java.util.TimeZone}'s package private {@code GMT_ID} field. */ diff --git a/src/test/java/org/apache/commons/lang3/test/SystemDefaultsSwitchTest.java b/src/test/java/org/apache/commons/lang3/test/SystemDefaultsSwitchTest.java index f2cd6f52c..ed152bb79 100644 --- a/src/test/java/org/apache/commons/lang3/test/SystemDefaultsSwitchTest.java +++ b/src/test/java/org/apache/commons/lang3/test/SystemDefaultsSwitchTest.java @@ -21,6 +21,7 @@ import static org.junit.Assert.assertEquals; import java.util.Locale; import java.util.TimeZone; +import org.apache.commons.lang3.time.FastTimeZone; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Rule; @@ -46,7 +47,7 @@ public class SystemDefaultsSwitchTest { TEST_DEFAULT_LOCALE = Locale.getDefault(); DEFAULT_TIMEZONE_BEFORE_TEST = TimeZone.getDefault(); - final TimeZone utc = TimeZone.getTimeZone("UTC"); + final TimeZone utc = FastTimeZone.getGmtTimeZone(); if (!DEFAULT_TIMEZONE_BEFORE_TEST.equals(utc)) { TimeZone.setDefault(utc); } else { diff --git a/src/test/java/org/apache/commons/lang3/time/DateFormatUtilsTest.java b/src/test/java/org/apache/commons/lang3/time/DateFormatUtilsTest.java index a938caad4..603e7def9 100644 --- a/src/test/java/org/apache/commons/lang3/time/DateFormatUtilsTest.java +++ b/src/test/java/org/apache/commons/lang3/time/DateFormatUtilsTest.java @@ -57,7 +57,7 @@ public class DateFormatUtilsTest { //----------------------------------------------------------------------- @Test public void testFormat() { - final Calendar c = Calendar.getInstance(TimeZone.getTimeZone("UTC")); + final Calendar c = Calendar.getInstance(FastTimeZone.getGmtTimeZone()); c.set(2005, Calendar.JANUARY, 1, 12, 0, 0); c.setTimeZone(TimeZone.getDefault()); final StringBuilder buffer = new StringBuilder (); @@ -81,7 +81,7 @@ public class DateFormatUtilsTest { //----------------------------------------------------------------------- @Test public void testFormatCalendar() { - final Calendar c = Calendar.getInstance(TimeZone.getTimeZone("UTC")); + final Calendar c = Calendar.getInstance(FastTimeZone.getGmtTimeZone()); c.set(2005, Calendar.JANUARY, 1, 12, 0, 0); c.setTimeZone(TimeZone.getDefault()); final StringBuilder buffer = new StringBuilder (); @@ -104,7 +104,7 @@ public class DateFormatUtilsTest { @Test public void testFormatUTC() { - final Calendar c = Calendar.getInstance(TimeZone.getTimeZone("UTC")); + final Calendar c = Calendar.getInstance(FastTimeZone.getGmtTimeZone()); c.set(2005, Calendar.JANUARY, 1, 12, 0, 0); assertEquals ("2005-01-01T12:00:00", DateFormatUtils.formatUTC(c.getTime(), DateFormatUtils.ISO_DATETIME_FORMAT.getPattern())); @@ -139,7 +139,7 @@ public class DateFormatUtilsTest { } private void testUTC(final String expectedValue, final String pattern) { - final TimeZone timeZone = TimeZone.getTimeZone("UTC"); + final TimeZone timeZone = FastTimeZone.getGmtTimeZone(); assertFormats(expectedValue, pattern, timeZone, createFebruaryTestDate(timeZone)); } @@ -180,7 +180,7 @@ public class DateFormatUtilsTest { assertFormats("Sun, 08 Jun 2003 10:11:12 -0300", DateFormatUtils.SMTP_DATETIME_FORMAT.getPattern(), timeZone, june); - timeZone = TimeZone.getTimeZone("UTC"); + timeZone = FastTimeZone.getGmtTimeZone(); june = createJuneTestDate(timeZone); assertFormats("Sun, 08 Jun 2003 10:11:12 +0000", DateFormatUtils.SMTP_DATETIME_FORMAT.getPattern(), timeZone, june); diff --git a/src/test/java/org/apache/commons/lang3/time/DurationFormatUtilsTest.java b/src/test/java/org/apache/commons/lang3/time/DurationFormatUtilsTest.java index b5eb0fac8..7dd3c8eb4 100644 --- a/src/test/java/org/apache/commons/lang3/time/DurationFormatUtilsTest.java +++ b/src/test/java/org/apache/commons/lang3/time/DurationFormatUtilsTest.java @@ -452,7 +452,7 @@ public class DurationFormatUtilsTest { @Test public void testEdgeDurations() { // This test case must use a time zone without DST - TimeZone.setDefault(TimeZone.getTimeZone("UTC")); + TimeZone.setDefault(FastTimeZone.getGmtTimeZone()); assertEqualDuration( "01", new int[] { 2006, 0, 15, 0, 0, 0 }, new int[] { 2006, 2, 10, 0, 0, 0 }, "MM"); assertEqualDuration( "12", new int[] { 2005, 0, 15, 0, 0, 0 }, diff --git a/src/test/java/org/apache/commons/lang3/time/FastDateFormatTest.java b/src/test/java/org/apache/commons/lang3/time/FastDateFormatTest.java index cf7c8fea8..be2d801ce 100644 --- a/src/test/java/org/apache/commons/lang3/time/FastDateFormatTest.java +++ b/src/test/java/org/apache/commons/lang3/time/FastDateFormatTest.java @@ -311,7 +311,7 @@ public class FastDateFormatTest { @Test public void testLANG_1152() { - final TimeZone utc = TimeZone.getTimeZone("UTC"); + final TimeZone utc = FastTimeZone.getGmtTimeZone(); final Date date = new Date(Long.MAX_VALUE); String dateAsString = FastDateFormat.getInstance("yyyy-MM-dd", utc, Locale.US).format(date); diff --git a/src/test/java/org/apache/commons/lang3/time/FastDatePrinterTest.java b/src/test/java/org/apache/commons/lang3/time/FastDatePrinterTest.java index ff9180ce5..e6243e41b 100644 --- a/src/test/java/org/apache/commons/lang3/time/FastDatePrinterTest.java +++ b/src/test/java/org/apache/commons/lang3/time/FastDatePrinterTest.java @@ -265,7 +265,7 @@ public class FastDatePrinterTest { @SystemDefaults(timezone="UTC") @Test public void testTimeZoneAsZ() throws Exception { - final Calendar c = Calendar.getInstance(TimeZone.getTimeZone("UTC")); + final Calendar c = Calendar.getInstance(FastTimeZone.getGmtTimeZone()); final FastDateFormat noColonFormat = FastDateFormat.getInstance("Z"); assertEquals("+0000", noColonFormat.format(c)); diff --git a/src/test/java/org/apache/commons/lang3/time/FastTimeZoneTest.java b/src/test/java/org/apache/commons/lang3/time/FastTimeZoneTest.java new file mode 100644 index 000000000..acd750097 --- /dev/null +++ b/src/test/java/org/apache/commons/lang3/time/FastTimeZoneTest.java @@ -0,0 +1,99 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.commons.lang3.time; + +import org.junit.Assert; +import org.junit.Test; + +import java.util.TimeZone; + +/** + * Tests for FastTimeZone + */ +public class FastTimeZoneTest { + + private static final int HOURS_23 = 23 * 60 * 60 * 1000; + private static final int HOURS_2 = 2 * 60 * 60 * 1000; + private static final int MINUTES_59 = 59 * 60 * 1000; + private static final int MINUTES_5 = 5 * 60 * 1000; + + @Test + public void testGetGmtTimeZone() { + Assert.assertEquals(0, FastTimeZone.getGmtTimeZone().getRawOffset()); + } + + @Test + public void testBareGmt() { + Assert.assertEquals(FastTimeZone.getGmtTimeZone(), FastTimeZone.getTimeZone("GMT")); + } + + @Test + public void testZ() { + Assert.assertEquals(FastTimeZone.getGmtTimeZone(), FastTimeZone.getTimeZone("Z")); + } + + @Test + public void testUTC() { + Assert.assertEquals(FastTimeZone.getGmtTimeZone(), FastTimeZone.getTimeZone("UTC")); + } + + @Test + public void testZeroOffsetsReturnSingleton() { + Assert.assertEquals(FastTimeZone.getGmtTimeZone(), FastTimeZone.getTimeZone("+0")); + Assert.assertEquals(FastTimeZone.getGmtTimeZone(), FastTimeZone.getTimeZone("-0")); + } + + @Test + public void testOlson() { + Assert.assertEquals(TimeZone.getTimeZone("America/New_York"), FastTimeZone.getTimeZone("America/New_York")); + } + + @Test + public void testGmtPrefix() { + Assert.assertEquals(HOURS_23, FastTimeZone.getGmtTimeZone("GMT+23:00").getRawOffset()); + Assert.assertEquals(-HOURS_23, FastTimeZone.getGmtTimeZone("GMT-23:00").getRawOffset()); + } + + @Test + public void testSign() { + Assert.assertEquals(HOURS_23, FastTimeZone.getGmtTimeZone("+23:00").getRawOffset()); + Assert.assertEquals(HOURS_2, FastTimeZone.getGmtTimeZone("+2:00").getRawOffset()); + Assert.assertEquals(-HOURS_23, FastTimeZone.getGmtTimeZone("-23:00").getRawOffset()); + Assert.assertEquals(-HOURS_2, FastTimeZone.getGmtTimeZone("-2:00").getRawOffset()); + } + + @Test + public void testHoursColonMinutes() { + Assert.assertEquals(HOURS_23, FastTimeZone.getGmtTimeZone("23:00").getRawOffset()); + Assert.assertEquals(HOURS_2, FastTimeZone.getGmtTimeZone("2:00").getRawOffset()); + Assert.assertEquals(MINUTES_59, FastTimeZone.getGmtTimeZone("00:59").getRawOffset()); + Assert.assertEquals(MINUTES_5, FastTimeZone.getGmtTimeZone("00:5").getRawOffset()); + Assert.assertEquals(HOURS_23+MINUTES_59, FastTimeZone.getGmtTimeZone("23:59").getRawOffset()); + Assert.assertEquals(HOURS_2+MINUTES_5, FastTimeZone.getGmtTimeZone("2:5").getRawOffset()); + } + + @Test + public void testHoursMinutes() { + Assert.assertEquals(HOURS_23, FastTimeZone.getGmtTimeZone("2300").getRawOffset()); + Assert.assertEquals(HOURS_2, FastTimeZone.getGmtTimeZone("0200").getRawOffset()); + Assert.assertEquals(MINUTES_59, FastTimeZone.getGmtTimeZone("0059").getRawOffset()); + Assert.assertEquals(MINUTES_5, FastTimeZone.getGmtTimeZone("0005").getRawOffset()); + Assert.assertEquals(HOURS_23+MINUTES_59, FastTimeZone.getGmtTimeZone("2359").getRawOffset()); + Assert.assertEquals(HOURS_2+MINUTES_5, FastTimeZone.getGmtTimeZone("0205").getRawOffset()); + } + +} diff --git a/src/test/java/org/apache/commons/lang3/time/GmtTimeZoneTest.java b/src/test/java/org/apache/commons/lang3/time/GmtTimeZoneTest.java new file mode 100644 index 000000000..b4c139b67 --- /dev/null +++ b/src/test/java/org/apache/commons/lang3/time/GmtTimeZoneTest.java @@ -0,0 +1,92 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.commons.lang3.time; + +import org.junit.Assert; +import org.junit.Test; + +/** + * Tests for GmtTimeZone + */ +public class GmtTimeZoneTest { + + @Test(expected = IllegalArgumentException.class) + public void hoursOutOfRange() { + new GmtTimeZone(false, 24, 0); + } + + @Test + public void hoursInRange() { + Assert.assertEquals(23 * 60 * 60 * 1000, new GmtTimeZone(false, 23, 0).getRawOffset()); + } + + @Test(expected = IllegalArgumentException.class) + public void minutesOutOfRange() { + new GmtTimeZone(false, 0, 60); + } + + @Test + public void minutesInRange() { + Assert.assertEquals(59 * 60 * 1000, new GmtTimeZone(false, 0, 59).getRawOffset()); + } + + @Test + public void getOffset() { + Assert.assertEquals(0, new GmtTimeZone(false, 0, 0).getOffset(234304)); + } + + @Test(expected = UnsupportedOperationException.class) + public void setRawOffset() { + new GmtTimeZone(false, 0, 0).setRawOffset(0); + } + + @Test + public void getRawOffset() { + Assert.assertEquals(0, new GmtTimeZone(false, 0, 0).getRawOffset()); + } + + @Test + public void getID() { + Assert.assertEquals("GMT+00:00", new GmtTimeZone(false, 0, 0).getID()); + Assert.assertEquals("GMT+01:02", new GmtTimeZone(false, 1, 2).getID()); + Assert.assertEquals("GMT+11:22", new GmtTimeZone(false, 11, 22).getID()); + Assert.assertEquals("GMT-01:02", new GmtTimeZone(true, 1, 2).getID()); + Assert.assertEquals("GMT-11:22", new GmtTimeZone(true, 11, 22).getID()); + } + + @Test + public void useDaylightTime() { + Assert.assertFalse(new GmtTimeZone(false, 0, 0).useDaylightTime()); + } + + @Test + public void inDaylightTime() { + Assert.assertFalse(new GmtTimeZone(false, 0, 0).useDaylightTime()); + } + + @Test + public void testToString() { + Assert.assertEquals("[GmtTimeZone id=\"GMT-12:00\",offset=-43200000]", + new GmtTimeZone(true, 12, 0).toString()); + } + + @Test + public void testGetOffset() { + Assert.assertEquals(-(6 * 60 + 30) * 60 * 1000, + new GmtTimeZone(true, 6, 30).getOffset(1, 1, 1, 1, 1, 1)); + } +}