Repository: commons-lang
Updated Branches:
  refs/heads/master 15d550321 -> 1dbfaeecb


[LANG-1355] TimeZone.getTimeZone() in FastDateParser causes resource
contention</action>. This closes #296.

Project: http://git-wip-us.apache.org/repos/asf/commons-lang/repo
Commit: http://git-wip-us.apache.org/repos/asf/commons-lang/commit/1dbfaeec
Tree: http://git-wip-us.apache.org/repos/asf/commons-lang/tree/1dbfaeec
Diff: http://git-wip-us.apache.org/repos/asf/commons-lang/diff/1dbfaeec

Branch: refs/heads/master
Commit: 1dbfaeecbd104a6edae43fcd3350c06a7cb51146
Parents: 15d5503
Author: Chas Honton <c...@honton.org>
Authored: Tue Oct 10 11:58:29 2017 -0600
Committer: Gary Gregory <ggreg...@apache.org>
Committed: Tue Oct 10 11:58:29 2017 -0600

----------------------------------------------------------------------
 src/changes/changes.xml                         |   1 +
 .../commons/lang3/time/DateFormatUtils.java     |   2 +-
 .../commons/lang3/time/FastDateParser.java      |  13 +--
 .../apache/commons/lang3/time/FastTimeZone.java |  95 +++++++++++++++++
 .../apache/commons/lang3/time/GmtTimeZone.java  | 106 +++++++++++++++++++
 .../apache/commons/lang3/time/TimeZones.java    |   4 +
 .../lang3/test/SystemDefaultsSwitchTest.java    |   3 +-
 .../commons/lang3/time/DateFormatUtilsTest.java |  10 +-
 .../lang3/time/DurationFormatUtilsTest.java     |   2 +-
 .../commons/lang3/time/FastDateFormatTest.java  |   2 +-
 .../commons/lang3/time/FastDatePrinterTest.java |   2 +-
 .../commons/lang3/time/FastTimeZoneTest.java    |  99 +++++++++++++++++
 .../commons/lang3/time/GmtTimeZoneTest.java     |  92 ++++++++++++++++
 13 files changed, 411 insertions(+), 20 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/commons-lang/blob/1dbfaeec/src/changes/changes.xml
----------------------------------------------------------------------
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 55e8c0c..c4491ee 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -46,6 +46,7 @@ The <action> type attribute can be add,update,fix,remove.
   <body>
 
   <release version="3.7" date="2017-MM-DD" description="New features and bug 
fixes. Requires Java 7.">
+    <action issue="LANG-1355" type="add" dev="ggregory" due-to="Chas 
Honton">TimeZone.getTimeZone() in FastDateParser causes resource contention (PR 
#296.)</action>
     <action issue="LANG-1348" type="fix" dev="pschumacher" 
due-to="mbusso">StackOverflowError on TypeUtils.toString(...) for a generic 
return type of Enum.valueOf</action>
     <action issue="LANG-1346" type="update" dev="pschumacher">Remove 
deprecation from RandomStringUtils</action>
     <action issue="LANG-1350" type="fix" dev="ggregory" due-to="Brett 
Kail">ConstructorUtils.invokeConstructor(Class, Object...) regression</action>

http://git-wip-us.apache.org/repos/asf/commons-lang/blob/1dbfaeec/src/main/java/org/apache/commons/lang3/time/DateFormatUtils.java
----------------------------------------------------------------------
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 09d2c52..b353e0d 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.

http://git-wip-us.apache.org/repos/asf/commons-lang/blob/1dbfaeec/src/main/java/org/apache/commons/lang3/time/FastDateParser.java
----------------------------------------------------------------------
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 3c8fe8c..3381558 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}))");

http://git-wip-us.apache.org/repos/asf/commons-lang/blob/1dbfaeec/src/main/java/org/apache/commons/lang3/time/FastTimeZone.java
----------------------------------------------------------------------
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 0000000..3962479
--- /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. <em>[GMT] (+|-) Hours [[:] Minutes]</em>
+     *
+     * @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
+     * <em>(GMT)? hh?(:?mm?)?</em>, 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) == '-';
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/commons-lang/blob/1dbfaeec/src/main/java/org/apache/commons/lang3/time/GmtTimeZone.java
----------------------------------------------------------------------
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 0000000..1a7462b
--- /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;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/commons-lang/blob/1dbfaeec/src/main/java/org/apache/commons/lang3/time/TimeZones.java
----------------------------------------------------------------------
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 634a9e3..5a75690 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.
      */

http://git-wip-us.apache.org/repos/asf/commons-lang/blob/1dbfaeec/src/test/java/org/apache/commons/lang3/test/SystemDefaultsSwitchTest.java
----------------------------------------------------------------------
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 f2cd6f5..ed152bb 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 {

http://git-wip-us.apache.org/repos/asf/commons-lang/blob/1dbfaeec/src/test/java/org/apache/commons/lang3/time/DateFormatUtilsTest.java
----------------------------------------------------------------------
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 a938caa..603e7de 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);

http://git-wip-us.apache.org/repos/asf/commons-lang/blob/1dbfaeec/src/test/java/org/apache/commons/lang3/time/DurationFormatUtilsTest.java
----------------------------------------------------------------------
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 b5eb0fa..7dd3c8e 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 },

http://git-wip-us.apache.org/repos/asf/commons-lang/blob/1dbfaeec/src/test/java/org/apache/commons/lang3/time/FastDateFormatTest.java
----------------------------------------------------------------------
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 cf7c8fe..be2d801 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);

http://git-wip-us.apache.org/repos/asf/commons-lang/blob/1dbfaeec/src/test/java/org/apache/commons/lang3/time/FastDatePrinterTest.java
----------------------------------------------------------------------
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 ff9180c..e6243e4 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));
 

http://git-wip-us.apache.org/repos/asf/commons-lang/blob/1dbfaeec/src/test/java/org/apache/commons/lang3/time/FastTimeZoneTest.java
----------------------------------------------------------------------
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 0000000..acd7500
--- /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());
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/commons-lang/blob/1dbfaeec/src/test/java/org/apache/commons/lang3/time/GmtTimeZoneTest.java
----------------------------------------------------------------------
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 0000000..b4c139b
--- /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));
+    }
+}

Reply via email to