You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by dj...@apache.org on 2014/09/28 12:11:18 UTC

svn commit: r1628061 - in /commons/proper/lang/trunk/src: changes/ main/java/org/apache/commons/lang3/time/ test/java/org/apache/commons/lang3/time/

Author: djones
Date: Sun Sep 28 10:11:17 2014
New Revision: 1628061

URL: http://svn.apache.org/r1628061
Log:
Added missing support for ISO 8601 parsing and printing using "ZZ" pattern (code now matches Javadoc). Addresses LANG-1000.

Modified:
    commons/proper/lang/trunk/src/changes/changes.xml
    commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/time/FastDateParser.java
    commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/time/FastDatePrinter.java
    commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/time/DateFormatUtilsTest.java
    commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/time/FastDatePrinterTest.java

Modified: commons/proper/lang/trunk/src/changes/changes.xml
URL: http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/changes/changes.xml?rev=1628061&r1=1628060&r2=1628061&view=diff
==============================================================================
--- commons/proper/lang/trunk/src/changes/changes.xml [utf-8] (original)
+++ commons/proper/lang/trunk/src/changes/changes.xml [utf-8] Sun Sep 28 10:11:17 2014
@@ -22,6 +22,7 @@
   <body>
 
   <release version="3.4" date="tba" description="tba">
+    <action issue="LANG-1000" type="fix" dev="djones">ParseException when trying to parse UTC dates with Z as zone designator using DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT</action>
   	<action issue="LANG-1035" type="fix" dev="djones">Javadoc for EqualsBuilder.reflectionEquals() is unclear</action>
     <action issue="LANG-1020" type="update" dev="britter" due-to="Libor Ondrusek">Improve performance of normalize space</action>
     <action issue="LANG-1033" type="add" dev="ggregory">Add StringUtils.countMatches(CharSequence, char)</action>

Modified: commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/time/FastDateParser.java
URL: http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/time/FastDateParser.java?rev=1628061&r1=1628060&r2=1628061&view=diff
==============================================================================
--- commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/time/FastDateParser.java (original)
+++ commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/time/FastDateParser.java Sun Sep 28 10:11:17 2014
@@ -513,6 +513,10 @@ public class FastDateParser implements D
         case 'y':
             return formatField.length()>2 ?LITERAL_YEAR_STRATEGY :ABBREVIATED_YEAR_STRATEGY;
         case 'Z':
+            if (formatField.equals("ZZ")) {
+                return ISO_8601_STRATEGY;
+            }
+            //$FALL-THROUGH$
         case 'z':
             return getLocaleSpecificStrategy(Calendar.ZONE_OFFSET, definingCalendar);
         }
@@ -814,6 +818,32 @@ public class FastDateParser implements D
             cal.setTimeZone(tz);
         }
     }
+    
+    private static class ISO8601TimeZoneStrategy extends Strategy {
+        // Z, +hh, -hh, +hhmm, -hhmm, +hh:mm or -hh:mm 
+        private static final String PATTERN = "(Z|(?:[+-]\\d{2}(?::?\\d{2})?))";
+        
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        boolean addRegex(FastDateParser parser, StringBuilder regex) {
+            regex.append(PATTERN);
+            return true;
+        }
+        
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        void setCalendar(FastDateParser parser, Calendar cal, String value) {
+            if (value.equals("Z")) {
+                cal.setTimeZone(TimeZone.getTimeZone("UTC"));
+            } else {
+                cal.setTimeZone(TimeZone.getTimeZone("GMT" + value));
+            }
+        }
+    }
 
     private static final Strategy NUMBER_MONTH_STRATEGY = new NumberStrategy(Calendar.MONTH) {
         @Override
@@ -844,4 +874,5 @@ public class FastDateParser implements D
     private static final Strategy MINUTE_STRATEGY = new NumberStrategy(Calendar.MINUTE);
     private static final Strategy SECOND_STRATEGY = new NumberStrategy(Calendar.SECOND);
     private static final Strategy MILLISECOND_STRATEGY = new NumberStrategy(Calendar.MILLISECOND);
+    private static final Strategy ISO_8601_STRATEGY = new ISO8601TimeZoneStrategy();
 }

Modified: commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/time/FastDatePrinter.java
URL: http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/time/FastDatePrinter.java?rev=1628061&r1=1628060&r2=1628061&view=diff
==============================================================================
--- commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/time/FastDatePrinter.java (original)
+++ commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/time/FastDatePrinter.java Sun Sep 28 10:11:17 2014
@@ -274,6 +274,8 @@ public class FastDatePrinter implements 
             case 'Z': // time zone (value)
                 if (tokenLen == 1) {
                     rule = TimeZoneNumberRule.INSTANCE_NO_COLON;
+                } else if (tokenLen == 2) {
+                    rule = TimeZoneNumberRule.INSTANCE_ISO_8601;
                 } else {
                     rule = TimeZoneNumberRule.INSTANCE_COLON;
                 }
@@ -1173,18 +1175,22 @@ public class FastDatePrinter implements 
      * or {@code +/-HH:MM}.</p>
      */
     private static class TimeZoneNumberRule implements Rule {
-        static final TimeZoneNumberRule INSTANCE_COLON = new TimeZoneNumberRule(true);
-        static final TimeZoneNumberRule INSTANCE_NO_COLON = new TimeZoneNumberRule(false);
+        static final TimeZoneNumberRule INSTANCE_COLON = new TimeZoneNumberRule(true, false);
+        static final TimeZoneNumberRule INSTANCE_NO_COLON = new TimeZoneNumberRule(false, false);
+        static final TimeZoneNumberRule INSTANCE_ISO_8601 = new TimeZoneNumberRule(true, true);
 
         final boolean mColon;
+        final boolean mISO8601;
 
         /**
          * Constructs an instance of {@code TimeZoneNumberRule} with the specified properties.
          *
          * @param colon add colon between HH and MM in the output if {@code true}
+         * @param iso8601 create an ISO 8601 format output
          */
-        TimeZoneNumberRule(final boolean colon) {
+        TimeZoneNumberRule(final boolean colon, final boolean iso8601) {
             mColon = colon;
+            mISO8601 = iso8601;
         }
 
         /**
@@ -1200,6 +1206,11 @@ public class FastDatePrinter implements 
          */
         @Override
         public void appendTo(final StringBuffer buffer, final Calendar calendar) {
+            if (mISO8601 && calendar.getTimeZone().getID().equals("UTC")) {
+                buffer.append("Z");
+                return;
+            }
+            
             int offset = calendar.get(Calendar.ZONE_OFFSET) + calendar.get(Calendar.DST_OFFSET);
 
             if (offset < 0) {

Modified: commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/time/DateFormatUtilsTest.java
URL: http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/time/DateFormatUtilsTest.java?rev=1628061&r1=1628060&r2=1628061&view=diff
==============================================================================
--- commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/time/DateFormatUtilsTest.java (original)
+++ commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/time/DateFormatUtilsTest.java Sun Sep 28 10:11:17 2014
@@ -17,10 +17,13 @@
 package org.apache.commons.lang3.time;
 
 import org.junit.Test;
+
 import static org.junit.Assert.*;
+
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Modifier;
 import java.util.Calendar;
+import java.util.Date;
 import java.util.Locale;
 import java.util.TimeZone;
 
@@ -103,7 +106,7 @@ public class DateFormatUtilsTest {
     }
     
     @Test
-    public void testDateTimeISO(){
+    public void testDateTimeISO() throws Exception {
         final TimeZone timeZone = TimeZone.getTimeZone("GMT-3");
         final Calendar cal = Calendar.getInstance(timeZone);
         cal.set(2002,1,23,9,11,12);
@@ -124,6 +127,14 @@ public class DateFormatUtilsTest {
         assertEquals("2002-02-23T09:11:12-03:00", text);
         text = DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.format(cal);
         assertEquals("2002-02-23T09:11:12-03:00", text);
+        
+        Calendar utcCal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
+        utcCal.set(2002, 1, 23, 9, 11, 12);
+        utcCal.set(Calendar.MILLISECOND, 0);
+        text = DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.format(utcCal);
+        assertEquals("2002-02-23T09:11:12Z", text);
+        Date date = DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.parse(text);
+        assertEquals(utcCal.getTime(), date);
     }
 
     @Test
@@ -249,4 +260,9 @@ public class DateFormatUtilsTest {
     }
     */
 
+    @Test
+    public void testLANG1000() throws Exception {
+        String date = "2013-11-18T12:48:05Z";
+        DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.parse(date);
+    }
 }

Modified: commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/time/FastDatePrinterTest.java
URL: http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/time/FastDatePrinterTest.java?rev=1628061&r1=1628060&r2=1628061&view=diff
==============================================================================
--- commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/time/FastDatePrinterTest.java (original)
+++ commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/time/FastDatePrinterTest.java Sun Sep 28 10:11:17 2014
@@ -16,10 +16,7 @@
  */
 package org.apache.commons.lang3.time;
 
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.*;
 
 import java.io.Serializable;
 import java.text.SimpleDateFormat;
@@ -286,4 +283,17 @@ public class FastDatePrinterTest {
         final String actualValue = FastDateFormat.getInstance(pattern).format(cal);
         assertEquals(expectedValue, actualValue);
     }
+    
+    @Test
+    public void testTimeZoneAsZ() throws Exception {
+        Calendar c = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
+        FastDateFormat noColonFormat = FastDateFormat.getInstance("Z");
+        assertEquals("+0000", noColonFormat.format(c));
+        
+        FastDateFormat isoFormat = FastDateFormat.getInstance("ZZ");
+        assertEquals("Z", isoFormat.format(c));
+        
+        FastDateFormat colonFormat = FastDateFormat.getInstance("ZZZ");
+        assertEquals("+00:00", colonFormat.format(c));
+    }
 }