Seems a little extreme solution.  Exactly where does the FastDateParser
fail with non-Gregorian calendars?

The parser should just be setting fields on a Calendar object which does
the calculations.  Are the fields being properly parsed?  Is a proper
Calendar object being created?

chas


On 9/25/12 9:32 AM, "s...@apache.org" <s...@apache.org> wrote:

>Author: sebb
>Date: Tue Sep 25 16:32:20 2012
>New Revision: 1389976
>
>URL: http://svn.apache.org/viewvc?rev=1389976&view=rev
>Log:
>LANG-828 FastDateParser does not handle non-Gregorian calendars properly
>
>Modified:
>    commons/proper/lang/trunk/src/changes/changes.xml
>    
>commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/time/Fast
>DateParser.java
>    
>commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/time/Fast
>DateParserTest.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=1389976&r1=1389975&r2=1389976&view=diff
>==========================================================================
>====
>--- commons/proper/lang/trunk/src/changes/changes.xml (original)
>+++ commons/proper/lang/trunk/src/changes/changes.xml Tue Sep 25 16:32:20
>2012
>@@ -22,6 +22,7 @@
>   <body>
> 
>   <release version="3.2" date="TBA" description="Next release">
>+    <action issue="LANG-828" type="fix">FastDateParser does not handle
>non-Gregorian calendars properly</action>
>     <action issue="LANG-826" type="fix">FastDateParser does not handle
>non-ASCII digits correctly</action>
>     <action issue="LANG-825" type="add">Create StrBuilder APIs similar
>to String.format(String, Object...)</action>
>     <action issue="LANG-817" type="fix">Add
>org.apache.commons.lang3.SystemUtils.IS_OS_WINDOWS_8</action>
>
>Modified: 
>commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/time/Fast
>DateParser.java
>URL: 
>http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/main/java/org/a
>pache/commons/lang3/time/FastDateParser.java?rev=1389976&r1=1389975&r2=138
>9976&view=diff
>==========================================================================
>====
>--- 
>commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/time/Fast
>DateParser.java (original)
>+++ 
>commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/time/Fast
>DateParser.java Tue Sep 25 16:32:20 2012
>@@ -22,6 +22,7 @@ import java.io.Serializable;
> import java.text.DateFormatSymbols;
> import java.text.ParseException;
> import java.text.ParsePosition;
>+import java.text.SimpleDateFormat;
> import java.util.ArrayList;
> import java.util.Arrays;
> import java.util.Calendar;
>@@ -55,6 +56,13 @@ import java.util.regex.Pattern;
>  * <p>Timing tests indicate this class is as about as fast as
>SimpleDateFormat
>  * in single thread applications and about 25% faster in multi-thread
>applications.</p>
>  *
>+ * <p>Note that the code only handles Gregorian calendars. The following
>non-Gregorian
>+ * calendars use SimpleDateFormat internally, and so will be slower:
>+ * <ul>
>+ * <li>ja_JP_TH - Japanese Imperial</li>
>+ * <li>th_TH (any variant) - Thai Buddhist</li>
>+ * </ul>
>+ * </p>
>  * @since 3.2
>  */
> public class FastDateParser implements DateParser, Serializable {
>@@ -114,7 +122,17 @@ public class FastDateParser implements D
>         if(!patternMatcher.lookingAt()) {
>             throw new IllegalArgumentException("Invalid pattern");
>         }
>-        
>+
>+        String localeName = locale.toString();
>+        // These locales don't use the Gregorian calendar
>+        // See 
>http://docs.oracle.com/javase/6/docs/technotes/guides/intl/calendar.doc.ht
>ml
>+        if (localeName.equals("ja_JP_JP") ||
>localeName.startsWith("th_TH")) {
>+            collector.add(new SimpleDateFormatStrategy());
>+            strategies= collector.toArray(new
>Strategy[collector.size()]);
>+            parsePattern= Pattern.compile("(.*+)");
>+            return;
>+        }
>+
>         currentFormatField= patternMatcher.group();
>         Strategy currentStrategy= getStrategy(currentFormatField);
>         for(;;) {
>@@ -797,6 +815,38 @@ public class FastDateParser implements D
>         }        
>     }
> 
>+
>+    /**
>+     * Dummy strategy which delegates to SimpleDateFormat.
>+     */
>+    private static class SimpleDateFormatStrategy implements Strategy {
>+
>+        @Override
>+        public boolean isNumber() {
>+            return false;
>+        }
>+
>+        @Override
>+        public void setCalendar(FastDateParser parser, Calendar cal,
>String value) {
>+            String pat = parser.pattern;
>+            Locale loc = parser.locale;
>+            SimpleDateFormat sdf = new SimpleDateFormat(pat, loc);
>+            try {
>+                Date d = sdf.parse(value);
>+                cal.setTime(d);
>+            } catch (ParseException e) {
>+                throw new IllegalArgumentException(
>+                        "Unexpected error using pattern " + pat + " with
>locale " + loc.toString(), e);
>+            }
>+        }
>+
>+        @Override
>+        public boolean addRegex(FastDateParser parser, StringBuilder
>regex) {
>+            return false;
>+        }
>+        
>+    }
>+
>     private static final Strategy ERA_STRATEGY = new
>TextStrategy(Calendar.ERA);
>     private static final Strategy DAY_OF_WEEK_STRATEGY = new
>TextStrategy(Calendar.DAY_OF_WEEK);
>     private static final Strategy AM_PM_STRATEGY = new
>TextStrategy(Calendar.AM_PM);
>
>Modified: 
>commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/time/Fast
>DateParserTest.java
>URL: 
>http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/test/java/org/a
>pache/commons/lang3/time/FastDateParserTest.java?rev=1389976&r1=1389975&r2
>=1389976&view=diff
>==========================================================================
>====
>--- 
>commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/time/Fast
>DateParserTest.java (original)
>+++ 
>commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/time/Fast
>DateParserTest.java Tue Sep 25 16:32:20 2012
>@@ -19,7 +19,6 @@ package org.apache.commons.lang3.time;
> import static org.junit.Assert.assertEquals;
> import static org.junit.Assert.assertFalse;
> import static org.junit.Assert.assertTrue;
>-
> import java.io.Serializable;
> import java.text.ParseException;
> import java.text.SimpleDateFormat;
>@@ -31,6 +30,8 @@ import java.util.Locale;
> import java.util.Map;
> import java.util.TimeZone;
> 
>+import junit.framework.Assert;
>+
> import org.apache.commons.lang3.SerializationUtils;
> import org.junit.Test;
> 
>@@ -191,15 +192,37 @@ public class FastDateParserTest {
>     public void testParses() throws Exception {
>         for(Locale locale : Locale.getAvailableLocales()) {
>             for(TimeZone tz : new TimeZone[]{NEW_YORK, GMT}) {
>-                Calendar cal = Calendar.getInstance(tz);
>-                cal.clear();
>-                cal.set(2003, 1, 10);
>-                Date in = cal.getTime();
>-                for(String format : new String[]{LONG_FORMAT,
>SHORT_FORMAT}) {
>-                    SimpleDateFormat sdf = new
>SimpleDateFormat(LONG_FORMAT, locale);
>-                    String fmt = sdf.format(in);
>-                    Date out = sdf.parse(fmt);
>-                    assertEquals(locale.toString()+" "+ format+ "
>"+tz.getID(), in, out);
>+                Calendar cal = Calendar.getInstance(tz);
>+                for(int year : new int[]{2003, 1940, 1868, 1867, 0,
>-1940}) {
>+                    //
>http://docs.oracle.com/javase/6/docs/technotes/guides/intl/calendar.doc.ht
>ml
>+                    if (year < 1868 &&
>locale.toString().equals("ja_JP_JP")) {
>+                        continue; // Japanese imperial calendar does not
>support eras before 1868
>+                    }
>+                    cal.clear();
>+                    if (year < 0) {
>+                        cal.set(-year, 1, 10);
>+                        cal.set(Calendar.ERA, GregorianCalendar.BC);
>+                    } else {
>+                        cal.set(year, 1, 10);
>+                    }
>+                    Date in = cal.getTime();
>+                    for(String format : new String[]{LONG_FORMAT,
>SHORT_FORMAT}) {
>+                        SimpleDateFormat sdf = new
>SimpleDateFormat(format, locale);
>+                        if (format.equals(SHORT_FORMAT)) {
>+                            if (year < 1930) {
>+                                sdf.set2DigitYearStart(cal.getTime());
>+                            }
>+                        }
>+                        String fmt = sdf.format(in);
>+                        try {
>+                            Date out = sdf.parse(fmt);
>+                 
>+                            assertEquals(locale.toString()+" "+year+" "+
>format+ " "+tz.getID(), in, out);
>+                        } catch (ParseException pe) {
>+                            System.out.println(fmt+"
>"+locale.toString()+" "+year+" "+ format+ " "+tz.getID());
>+                            throw pe;
>+                        }
>+                    }
>                 }
>             }
>         }
>@@ -253,19 +276,28 @@ public class FastDateParserTest {
>         if (eraBC) {
>             cal.set(Calendar.ERA, GregorianCalendar.BC);
>         }
>+        boolean failed = false;
>         for(Locale locale : Locale.getAvailableLocales()) {
>+            // ja_JP_JP cannot handle dates before 1868 properly
>+            if (eraBC && format.equals(SHORT_FORMAT) &&
>locale.toString().equals("ja_JP_JP")) {
>+                continue;
>+            }
>             SimpleDateFormat sdf = new SimpleDateFormat(format, locale);
>             DateParser fdf = getInstance(format, locale);
> 
>             try {
>                 checkParse(locale, cal, sdf, fdf);
>             } catch(ParseException ex) {
>+                failed = true;
>                 // TODO: are these Java bugs?
>                 // ja_JP_JP, th_TH, and th_TH_TH fail with both eras
>because the generated era name does not match
>                 // ja_JP_JP fails with era BC because it converts to
>-2002
>                 System.out.println("Locale "+locale+ " failed with
>"+format+" era "+(eraBC?"BC":"AD")+"\n" + trimMessage(ex.toString()));
>             }
>         }
>+        if (failed) {
>+            Assert.fail("One or more tests failed, see above");
>+        }
>     }
> 
>     private String trimMessage(String msg) {
>
>


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@commons.apache.org
For additional commands, e-mail: dev-h...@commons.apache.org

Reply via email to