You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by Benedikt Ritter <br...@apache.org> on 2015/03/23 07:56:03 UTC

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

Charles, I think I've told you this several times now. Please add issues
you fix to changes.xml! This is necessary to automatically create release
notes.

Thank you.
Benedikt

2015-03-23 3:33 GMT+01:00 <ch...@apache.org>:

> Author: chas
> Date: Mon Mar 23 02:33:41 2015
> New Revision: 1668511
>
> URL: http://svn.apache.org/r1668511
> Log:
> LANG-1101 FastDateParser and FastDatePrinter support 'X' format
>
> Modified:
>
> 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/FastDateParserTest.java
>
> commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/time/FastDatePrinterTest.java
>
> 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=1668511&r1=1668510&r2=1668511&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
> Mon Mar 23 02:33:41 2015
> @@ -96,7 +96,10 @@ public class FastDateParser implements D
>
>      /**
>       * <p>Constructs a new FastDateParser.</p>
> -     *
> +     *
> +     * Use {@link FastDateFormat#getInstance(String, TimeZone, Locale)}
> or another variation of the
> +     * factory methods of {@link FastDateFormat} to get a cached
> FastDateParser instance.
> +        *
>       * @param pattern non-null {@link java.text.SimpleDateFormat}
> compatible
>       *  pattern
>       * @param timeZone non-null time zone to use
> @@ -467,13 +470,14 @@ public class FastDateParser implements D
>           * false, if this field is a constant value
>           */
>          abstract boolean addRegex(FastDateParser parser, StringBuilder
> regex);
> +
>      }
>
>      /**
>       * A <code>Pattern</code> to parse the user supplied SimpleDateFormat
> pattern
>       */
>      private static final Pattern formatPattern= Pattern.compile(
> -
> "D+|E+|F+|G+|H+|K+|M+|S+|W+|Z+|a+|d+|h+|k+|m+|s+|w+|y+|z+|''|'[^']++(''[^']*+)*+'|[^'A-Za-z]++");
> +
> "D+|E+|F+|G+|H+|K+|M+|S+|W+|X+|Z+|a+|d+|h+|k+|m+|s+|w+|y+|z+|''|'[^']++(''[^']*+)*+'|[^'A-Za-z]++");
>
>      /**
>       * Obtain a Strategy given a field from a SimpleDateFormat pattern
> @@ -524,6 +528,8 @@ public class FastDateParser implements D
>              return WEEK_OF_YEAR_STRATEGY;
>          case 'y':
>              return formatField.length()>2 ?LITERAL_YEAR_STRATEGY
> :ABBREVIATED_YEAR_STRATEGY;
> +        case 'X':
> +               return
> ISO8601TimeZoneStrategy.getStrategy(formatField.length());
>          case 'Z':
>              if (formatField.equals("ZZ")) {
>                  return ISO_8601_STRATEGY;
> @@ -834,14 +840,18 @@ public class FastDateParser implements D
>
>      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})?))";
> +       private final String pattern;
> +
> +        ISO8601TimeZoneStrategy(String pattern) {
> +               this.pattern = pattern;
> +        }
>
>          /**
>           * {@inheritDoc}
>           */
>          @Override
>          boolean addRegex(FastDateParser parser, StringBuilder regex) {
> -            regex.append(PATTERN);
> +            regex.append(pattern);
>              return true;
>          }
>
> @@ -856,6 +866,23 @@ public class FastDateParser implements D
>                  cal.setTimeZone(TimeZone.getTimeZone("GMT" + value));
>              }
>          }
> +
> +        private static final Strategy ISO_8601_1_STRATEGY = new
> ISO8601TimeZoneStrategy("(Z|(?:[+-]\\d{2}))");
> +        private static final Strategy ISO_8601_2_STRATEGY = new
> ISO8601TimeZoneStrategy("(Z|(?:[+-]\\d{2}\\d{2}))");
> +        private static final Strategy ISO_8601_3_STRATEGY = new
> ISO8601TimeZoneStrategy("(Z|(?:[+-]\\d{2}(?::)\\d{2}))");
> +
> +               static Strategy getStrategy(int tokenLen) {
> +               switch(tokenLen) {
> +               case 1:
> +                       return ISO_8601_1_STRATEGY;
> +               case 2:
> +                       return ISO_8601_2_STRATEGY;
> +               case 3:
> +                       return ISO_8601_3_STRATEGY;
> +               default:
> +                       throw new IllegalArgumentException("invalid number
> of X");
> +               }
> +               }
>      }
>
>      private static final Strategy NUMBER_MONTH_STRATEGY = new
> NumberStrategy(Calendar.MONTH) {
> @@ -887,5 +914,7 @@ 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();
> +    private static final Strategy ISO_8601_STRATEGY = new
> ISO8601TimeZoneStrategy("(Z|(?:[+-]\\d{2}(?::?\\d{2})?))");
> +
> +
>  }
>
> 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=1668511&r1=1668510&r2=1668511&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
> Mon Mar 23 02:33:41 2015
> @@ -38,7 +38,7 @@ import org.apache.commons.lang3.Validate
>   * <p>FastDatePrinter is a fast and thread-safe version of
>   * {@link java.text.SimpleDateFormat}.</p>
>   *
> - * <p>To obtain a proxy to a FastDatePrinter, use {@link
> FastDateFormat#getInstance(String, TimeZone, Locale)}
> + * <p>To obtain a FastDatePrinter, use {@link
> FastDateFormat#getInstance(String, TimeZone, Locale)}
>   * or another variation of the factory methods of {@link
> FastDateFormat}.</p>
>   *
>   * <p>Since FastDatePrinter is thread safe, you can use a static member
> instance:</p>
> @@ -64,6 +64,10 @@ import org.apache.commons.lang3.Validate
>   * ISO 8601 full format time zones (eg. {@code +08:00} or {@code -11:00}).
>   * This introduces a minor incompatibility with Java 1.4, but at a gain of
>   * useful functionality.</p>
> + *
> + * <p>Starting with JDK7, ISO 8601 support was added using the pattern
> {@code 'X'}.
> + * To maintain compatibility, {@code 'ZZ'} will continue to be supported,
> but using
> + * one of the {@code 'X'} formats is recommended.
>   *
>   * <p>Javadoc cites for the year pattern: <i>For formatting, if the
> number of
>   * pattern letters is 2, the year is truncated to 2 digits; otherwise it
> is
> @@ -137,6 +141,8 @@ public class FastDatePrinter implements
>
>  //-----------------------------------------------------------------------
>      /**
>       * <p>Constructs a new FastDatePrinter.</p>
> +     * Use {@link FastDateFormat#getInstance(String, TimeZone, Locale)}
> or another variation of the
> +     * factory methods of {@link FastDateFormat} to get a cached
> FastDatePrinter instance.
>       *
>       * @param pattern  {@link java.text.SimpleDateFormat} compatible
> pattern
>       * @param timeZone  non-null time zone to use
> @@ -265,6 +271,9 @@ public class FastDatePrinter implements
>              case 'K': // hour in am/pm (0..11)
>                  rule = selectNumberRule(Calendar.HOUR, tokenLen);
>                  break;
> +            case 'X': // ISO 8601
> +               rule = Iso8601_Rule.getRule(tokenLen);
> +                break;
>              case 'z': // time zone (text)
>                  if (tokenLen >= 4) {
>                      rule = new TimeZoneNameRule(mTimeZone, mLocale,
> TimeZone.LONG);
> @@ -581,6 +590,11 @@ public class FastDatePrinter implements
>          init();
>      }
>
> +       private static void appendDigits(final StringBuffer buffer, final
> int value) {
> +               buffer.append((char)(value / 10 + '0'));
> +               buffer.append((char)(value % 10 + '0'));
> +       }
> +
>      // Rules
>
>  //-----------------------------------------------------------------------
>      /**
> @@ -588,7 +602,7 @@ public class FastDatePrinter implements
>       */
>      private interface Rule {
>          /**
> -         * Returns the estimated lentgh of the result.
> +         * Returns the estimated length of the result.
>           *
>           * @return the estimated length
>           */
> @@ -810,8 +824,7 @@ public class FastDatePrinter implements
>              if (value < 10) {
>                  buffer.append((char)(value + '0'));
>              } else {
> -                buffer.append((char)(value / 10 + '0'));
> -                buffer.append((char)(value % 10 + '0'));
> +               appendDigits(buffer, value);
>              }
>          }
>      }
> @@ -863,8 +876,7 @@ public class FastDatePrinter implements
>                  for (int i = mSize; --i >= 2; ) {
>                      buffer.append('0');
>                  }
> -                buffer.append((char)(value / 10 + '0'));
> -                buffer.append((char)(value % 10 + '0'));
> +                appendDigits(buffer, value);
>              } else {
>                  int digits;
>                  if (value < 1000) {
> @@ -918,8 +930,7 @@ public class FastDatePrinter implements
>          @Override
>          public final void appendTo(final StringBuffer buffer, final int
> value) {
>              if (value < 100) {
> -                buffer.append((char)(value / 10 + '0'));
> -                buffer.append((char)(value % 10 + '0'));
> +                appendDigits(buffer, value);
>              } else {
>                  buffer.append(Integer.toString(value));
>              }
> @@ -960,8 +971,7 @@ public class FastDatePrinter implements
>           */
>          @Override
>          public final void appendTo(final StringBuffer buffer, final int
> value) {
> -            buffer.append((char)(value / 10 + '0'));
> -            buffer.append((char)(value % 10 + '0'));
> +            appendDigits(buffer, value);
>          }
>      }
>
> @@ -999,8 +1009,7 @@ public class FastDatePrinter implements
>           */
>          @Override
>          public final void appendTo(final StringBuffer buffer, final int
> value) {
> -            buffer.append((char)(value / 10 + '0'));
> -            buffer.append((char)(value % 10 + '0'));
> +            appendDigits(buffer, value);
>          }
>      }
>
> @@ -1121,7 +1130,7 @@ public class FastDatePrinter implements
>          return value;
>      }
>
> -    /**
> +       /**
>       * <p>Inner class to output a time zone name.</p>
>       */
>      private static class TimeZoneNameRule implements Rule {
> @@ -1178,7 +1187,7 @@ public class FastDatePrinter implements
>          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;
>
> @@ -1221,16 +1230,95 @@ public class FastDatePrinter implements
>              }
>
>              final int hours = offset / (60 * 60 * 1000);
> -            buffer.append((char)(hours / 10 + '0'));
> -            buffer.append((char)(hours % 10 + '0'));
> +            appendDigits(buffer, hours);
>
>              if (mColon) {
>                  buffer.append(':');
>              }
>
>              final int minutes = offset / (60 * 1000) - 60 * hours;
> -            buffer.append((char)(minutes / 10 + '0'));
> -            buffer.append((char)(minutes % 10 + '0'));
> +            appendDigits(buffer, minutes);
> +        }
> +    }
> +
> +    /**
> +     * <p>Inner class to output a time zone as a number {@code +/-HHMM}
> +     * or {@code +/-HH:MM}.</p>
> +     */
> +    private static class Iso8601_Rule implements Rule {
> +
> +       // Sign TwoDigitHours or Z
> +        static final Iso8601_Rule ISO8601_HOURS = new Iso8601_Rule(3);
> +       // Sign TwoDigitHours Minutes or Z
> +        static final Iso8601_Rule ISO8601_HOURS_MINUTES = new
> Iso8601_Rule(5);
> +       // Sign TwoDigitHours : Minutes or Z
> +        static final Iso8601_Rule ISO8601_HOURS_COLON_MINUTES = new
> Iso8601_Rule(6);
> +
> +        static Iso8601_Rule getRule(int tokenLen) {
> +               switch(tokenLen) {
> +               case 1:
> +                       return Iso8601_Rule.ISO8601_HOURS;
> +               case 2:
> +                       return Iso8601_Rule.ISO8601_HOURS_MINUTES;
> +               case 3:
> +                       return Iso8601_Rule.ISO8601_HOURS_COLON_MINUTES;
> +               default:
> +                       throw new IllegalArgumentException("invalid number
> of X");
> +               }
> +       }
> +
> +        final int length;
> +
> +        /**
> +         * Constructs an instance of {@code Iso8601_Rule} with the
> specified properties.
> +         *
> +         * @param length The number of characters in output (unless Z is
> output)
> +         */
> +        Iso8601_Rule(final int length) {
> +               this.length = length;
> +        }
> +
> +        /**
> +         * {@inheritDoc}
> +         */
> +        @Override
> +        public int estimateLength() {
> +            return length;
> +        }
> +
> +        /**
> +         * {@inheritDoc}
> +         */
> +        @Override
> +        public void appendTo(final StringBuffer buffer, final Calendar
> calendar) {
> +            int zoneOffset = calendar.get(Calendar.ZONE_OFFSET);
> +                       if (zoneOffset == 0) {
> +                buffer.append("Z");
> +                return;
> +            }
> +
> +            int offset = zoneOffset + calendar.get(Calendar.DST_OFFSET);
> +
> +            if (offset < 0) {
> +                buffer.append('-');
> +                offset = -offset;
> +            } else {
> +                buffer.append('+');
> +            }
> +
> +            final int hours = offset / (60 * 60 * 1000);
> +            appendDigits(buffer, hours);
> +
> +            if (length<5) {
> +               return;
> +            }
> +
> +            if (length==6) {
> +                buffer.append(':');
> +            }
> +
> +            final int minutes = offset / (60 * 1000) - 60 * hours;
> +            appendDigits(buffer, minutes);
>          }
>      }
>
>
> Modified:
> commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/time/FastDateParserTest.java
> URL:
> http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/time/FastDateParserTest.java?rev=1668511&r1=1668510&r2=1668511&view=diff
>
> ==============================================================================
> ---
> commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/time/FastDateParserTest.java
> (original)
> +++
> commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/time/FastDateParserTest.java
> Mon Mar 23 02:33:41 2015
> @@ -56,6 +56,7 @@ public class FastDateParserTest {
>      private static final TimeZone REYKJAVIK =
> TimeZone.getTimeZone("Atlantic/Reykjavik");
>      private static final TimeZone NEW_YORK =
> TimeZone.getTimeZone("America/New_York");
>      private static final TimeZone GMT = TimeZone.getTimeZone("GMT");
> +    private static final TimeZone INDIA =
> TimeZone.getTimeZone("Asia/Calcutta");
>
>      private static final Locale SWEDEN = new Locale("sv", "SE");
>
> @@ -556,4 +557,63 @@ public class FastDateParserTest {
>          assertEquals(expected.getTime(), fdp.parse("14MAY2014"));
>          assertEquals(expected.getTime(), fdp.parse("14May2014"));
>      }
> +
> +       @Test(expected = IllegalArgumentException.class)
> +       public void test1806Argument() {
> +               getInstance("XXXX");
> +       }
> +
> +       private static Calendar initializeCalendar(TimeZone tz) {
> +               Calendar cal = Calendar.getInstance(tz);
> +               cal.set(Calendar.YEAR, 2001);
> +               cal.set(Calendar.MONTH, 1); // not daylight savings
> +               cal.set(Calendar.DAY_OF_MONTH, 4);
> +               cal.set(Calendar.HOUR_OF_DAY, 12);
> +               cal.set(Calendar.MINUTE, 8);
> +               cal.set(Calendar.SECOND, 56);
> +               cal.set(Calendar.MILLISECOND, 235);
> +               return cal;
> +       }
> +
> +       private static enum Expected1806 {
> +               India(INDIA, "+05", "+0530", "+05:30", true),
> +               Greenwich(GMT, "Z", "Z", "Z", false),
> +               NewYork(NEW_YORK, "-05", "-0500", "-05:00", false);
> +
> +               private Expected1806(TimeZone zone, String one, String
> two, String three, boolean hasHalfHourOffset) {
> +                       this.zone = zone;
> +                       this.one = one;
> +                       this.two = two;
> +                       this.three = three;
> +                       this.offset = hasHalfHourOffset ?30*60*1000 :0;
> +               }
> +
> +               final TimeZone zone;
> +               final String one;
> +               final String two;
> +               final String three;
> +               final long offset;
> +       }
> +
> +       @Test
> +       public void test1806() throws ParseException {
> +               String formatStub = "yyyy-MM-dd'T'HH:mm:ss.SSS";
> +               String dateStub = "2001-02-04T12:08:56.235";
> +
> +               for (Expected1806 trial : Expected1806.values()) {
> +                       Calendar cal = initializeCalendar(trial.zone);
> +
> +                       String message = trial.zone.getDisplayName()+";";
> +
> +                       DateParser parser = getInstance(formatStub+"X",
> trial.zone);
> +                       assertEquals(message+trial.one,
> cal.getTime().getTime(),
> parser.parse(dateStub+trial.one).getTime()-trial.offset);
> +
> +                       parser = getInstance(formatStub+"XX", trial.zone);
> +                       assertEquals(message+trial.two, cal.getTime(),
> parser.parse(dateStub+trial.two));
> +
> +                       parser = getInstance(formatStub+"XXX", trial.zone);
> +                       assertEquals(message+trial.three, cal.getTime(),
> parser.parse(dateStub+trial.three));
> +               }
> +       }
> +
>  }
>
> 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=1668511&r1=1668510&r2=1668511&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
> Mon Mar 23 02:33:41 2015
> @@ -19,6 +19,7 @@ package org.apache.commons.lang3.time;
>  import static org.junit.Assert.*;
>
>  import java.io.Serializable;
> +import java.text.ParseException;
>  import java.text.SimpleDateFormat;
>  import java.util.Calendar;
>  import java.util.Date;
> @@ -39,6 +40,8 @@ public class FastDatePrinterTest {
>
>      private static final String YYYY_MM_DD = "yyyy/MM/dd";
>      private static final TimeZone NEW_YORK =
> TimeZone.getTimeZone("America/New_York");
> +    private static final TimeZone GMT = TimeZone.getTimeZone("GMT");
> +    private static final TimeZone INDIA =
> TimeZone.getTimeZone("Asia/Calcutta");
>      private static final Locale SWEDEN = new Locale("sv", "SE");
>
>          DatePrinter getInstance(final String format) {
> @@ -272,4 +275,55 @@ public class FastDatePrinterTest {
>          FastDateFormat colonFormat = FastDateFormat.getInstance("ZZZ");
>          assertEquals("+00:00", colonFormat.format(c));
>      }
> +
> +       private static Calendar initializeCalendar(TimeZone tz) {
> +               Calendar cal = Calendar.getInstance(tz);
> +               cal.set(Calendar.YEAR, 2001);
> +               cal.set(Calendar.MONTH, 1); // not daylight savings
> +               cal.set(Calendar.DAY_OF_MONTH, 4);
> +               cal.set(Calendar.HOUR_OF_DAY, 12);
> +               cal.set(Calendar.MINUTE, 8);
> +               cal.set(Calendar.SECOND, 56);
> +               cal.set(Calendar.MILLISECOND, 235);
> +               return cal;
> +       }
> +
> +       @Test(expected = IllegalArgumentException.class)
> +       public void test1806Argument() {
> +               getInstance("XXXX");
> +       }
> +
> +       private static enum Expected1806 {
> +               India(INDIA, "+05", "+0530", "+05:30"), Greenwich(GMT,
> "Z", "Z", "Z"), NewYork(
> +                               NEW_YORK, "-05", "-0500", "-05:00");
> +
> +               private Expected1806(TimeZone zone, String one, String
> two, String three) {
> +                       this.zone = zone;
> +                       this.one = one;
> +                       this.two = two;
> +                       this.three = three;
> +               }
> +
> +               final TimeZone zone;
> +               final String one;
> +               final String two;
> +               final String three;
> +       }
> +
> +
> +       @Test
> +       public void test1806() throws ParseException {
> +               for (Expected1806 trial : Expected1806.values()) {
> +                       Calendar cal = initializeCalendar(trial.zone);
> +
> +                       DatePrinter printer = getInstance("X", trial.zone);
> +                       assertEquals(trial.one, printer.format(cal));
> +
> +                       printer = getInstance("XX", trial.zone);
> +                       assertEquals(trial.two, printer.format(cal));
> +
> +                       printer = getInstance("XXX", trial.zone);
> +                       assertEquals(trial.three, printer.format(cal));
> +               }
> +       }
>  }
>
>
>


-- 
http://people.apache.org/~britter/
http://www.systemoutprintln.de/
http://twitter.com/BenediktRitter
http://github.com/britter

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

Posted by Jacques Le Roux <ja...@les7arts.com>.
Hi All,

In case it would help, to automate this we (OFBiz team) use Jira release notes
For instance you have https://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310481&version=12326666
Simply put the Jira ref in your commits comments. This also provides a direct access to Fisheye if you use it 
https://confluence.atlassian.com/display/JIRA/Viewing+the+Code+Development+Information+for+an+Issue

HTH

Jacques

Le 23/03/2015 07:56, Benedikt Ritter a écrit :
> Charles, I think I've told you this several times now. Please add issues
> you fix to changes.xml! This is necessary to automatically create release
> notes.
>
> Thank you.
> Benedikt
>
> 2015-03-23 3:33 GMT+01:00 <ch...@apache.org>:
>
>> Author: chas
>> Date: Mon Mar 23 02:33:41 2015
>> New Revision: 1668511
>>
>> URL: http://svn.apache.org/r1668511
>> Log:
>> LANG-1101 FastDateParser and FastDatePrinter support 'X' format
>>
>> Modified:
>>
>> 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/FastDateParserTest.java
>>
>> commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/time/FastDatePrinterTest.java
>>
>> 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=1668511&r1=1668510&r2=1668511&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
>> Mon Mar 23 02:33:41 2015
>> @@ -96,7 +96,10 @@ public class FastDateParser implements D
>>
>>       /**
>>        * <p>Constructs a new FastDateParser.</p>
>> -     *
>> +     *
>> +     * Use {@link FastDateFormat#getInstance(String, TimeZone, Locale)}
>> or another variation of the
>> +     * factory methods of {@link FastDateFormat} to get a cached
>> FastDateParser instance.
>> +        *
>>        * @param pattern non-null {@link java.text.SimpleDateFormat}
>> compatible
>>        *  pattern
>>        * @param timeZone non-null time zone to use
>> @@ -467,13 +470,14 @@ public class FastDateParser implements D
>>            * false, if this field is a constant value
>>            */
>>           abstract boolean addRegex(FastDateParser parser, StringBuilder
>> regex);
>> +
>>       }
>>
>>       /**
>>        * A <code>Pattern</code> to parse the user supplied SimpleDateFormat
>> pattern
>>        */
>>       private static final Pattern formatPattern= Pattern.compile(
>> -
>> "D+|E+|F+|G+|H+|K+|M+|S+|W+|Z+|a+|d+|h+|k+|m+|s+|w+|y+|z+|''|'[^']++(''[^']*+)*+'|[^'A-Za-z]++");
>> +
>> "D+|E+|F+|G+|H+|K+|M+|S+|W+|X+|Z+|a+|d+|h+|k+|m+|s+|w+|y+|z+|''|'[^']++(''[^']*+)*+'|[^'A-Za-z]++");
>>
>>       /**
>>        * Obtain a Strategy given a field from a SimpleDateFormat pattern
>> @@ -524,6 +528,8 @@ public class FastDateParser implements D
>>               return WEEK_OF_YEAR_STRATEGY;
>>           case 'y':
>>               return formatField.length()>2 ?LITERAL_YEAR_STRATEGY
>> :ABBREVIATED_YEAR_STRATEGY;
>> +        case 'X':
>> +               return
>> ISO8601TimeZoneStrategy.getStrategy(formatField.length());
>>           case 'Z':
>>               if (formatField.equals("ZZ")) {
>>                   return ISO_8601_STRATEGY;
>> @@ -834,14 +840,18 @@ public class FastDateParser implements D
>>
>>       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})?))";
>> +       private final String pattern;
>> +
>> +        ISO8601TimeZoneStrategy(String pattern) {
>> +               this.pattern = pattern;
>> +        }
>>
>>           /**
>>            * {@inheritDoc}
>>            */
>>           @Override
>>           boolean addRegex(FastDateParser parser, StringBuilder regex) {
>> -            regex.append(PATTERN);
>> +            regex.append(pattern);
>>               return true;
>>           }
>>
>> @@ -856,6 +866,23 @@ public class FastDateParser implements D
>>                   cal.setTimeZone(TimeZone.getTimeZone("GMT" + value));
>>               }
>>           }
>> +
>> +        private static final Strategy ISO_8601_1_STRATEGY = new
>> ISO8601TimeZoneStrategy("(Z|(?:[+-]\\d{2}))");
>> +        private static final Strategy ISO_8601_2_STRATEGY = new
>> ISO8601TimeZoneStrategy("(Z|(?:[+-]\\d{2}\\d{2}))");
>> +        private static final Strategy ISO_8601_3_STRATEGY = new
>> ISO8601TimeZoneStrategy("(Z|(?:[+-]\\d{2}(?::)\\d{2}))");
>> +
>> +               static Strategy getStrategy(int tokenLen) {
>> +               switch(tokenLen) {
>> +               case 1:
>> +                       return ISO_8601_1_STRATEGY;
>> +               case 2:
>> +                       return ISO_8601_2_STRATEGY;
>> +               case 3:
>> +                       return ISO_8601_3_STRATEGY;
>> +               default:
>> +                       throw new IllegalArgumentException("invalid number
>> of X");
>> +               }
>> +               }
>>       }
>>
>>       private static final Strategy NUMBER_MONTH_STRATEGY = new
>> NumberStrategy(Calendar.MONTH) {
>> @@ -887,5 +914,7 @@ 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();
>> +    private static final Strategy ISO_8601_STRATEGY = new
>> ISO8601TimeZoneStrategy("(Z|(?:[+-]\\d{2}(?::?\\d{2})?))");
>> +
>> +
>>   }
>>
>> 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=1668511&r1=1668510&r2=1668511&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
>> Mon Mar 23 02:33:41 2015
>> @@ -38,7 +38,7 @@ import org.apache.commons.lang3.Validate
>>    * <p>FastDatePrinter is a fast and thread-safe version of
>>    * {@link java.text.SimpleDateFormat}.</p>
>>    *
>> - * <p>To obtain a proxy to a FastDatePrinter, use {@link
>> FastDateFormat#getInstance(String, TimeZone, Locale)}
>> + * <p>To obtain a FastDatePrinter, use {@link
>> FastDateFormat#getInstance(String, TimeZone, Locale)}
>>    * or another variation of the factory methods of {@link
>> FastDateFormat}.</p>
>>    *
>>    * <p>Since FastDatePrinter is thread safe, you can use a static member
>> instance:</p>
>> @@ -64,6 +64,10 @@ import org.apache.commons.lang3.Validate
>>    * ISO 8601 full format time zones (eg. {@code +08:00} or {@code -11:00}).
>>    * This introduces a minor incompatibility with Java 1.4, but at a gain of
>>    * useful functionality.</p>
>> + *
>> + * <p>Starting with JDK7, ISO 8601 support was added using the pattern
>> {@code 'X'}.
>> + * To maintain compatibility, {@code 'ZZ'} will continue to be supported,
>> but using
>> + * one of the {@code 'X'} formats is recommended.
>>    *
>>    * <p>Javadoc cites for the year pattern: <i>For formatting, if the
>> number of
>>    * pattern letters is 2, the year is truncated to 2 digits; otherwise it
>> is
>> @@ -137,6 +141,8 @@ public class FastDatePrinter implements
>>
>>   //-----------------------------------------------------------------------
>>       /**
>>        * <p>Constructs a new FastDatePrinter.</p>
>> +     * Use {@link FastDateFormat#getInstance(String, TimeZone, Locale)}
>> or another variation of the
>> +     * factory methods of {@link FastDateFormat} to get a cached
>> FastDatePrinter instance.
>>        *
>>        * @param pattern  {@link java.text.SimpleDateFormat} compatible
>> pattern
>>        * @param timeZone  non-null time zone to use
>> @@ -265,6 +271,9 @@ public class FastDatePrinter implements
>>               case 'K': // hour in am/pm (0..11)
>>                   rule = selectNumberRule(Calendar.HOUR, tokenLen);
>>                   break;
>> +            case 'X': // ISO 8601
>> +               rule = Iso8601_Rule.getRule(tokenLen);
>> +                break;
>>               case 'z': // time zone (text)
>>                   if (tokenLen >= 4) {
>>                       rule = new TimeZoneNameRule(mTimeZone, mLocale,
>> TimeZone.LONG);
>> @@ -581,6 +590,11 @@ public class FastDatePrinter implements
>>           init();
>>       }
>>
>> +       private static void appendDigits(final StringBuffer buffer, final
>> int value) {
>> +               buffer.append((char)(value / 10 + '0'));
>> +               buffer.append((char)(value % 10 + '0'));
>> +       }
>> +
>>       // Rules
>>
>>   //-----------------------------------------------------------------------
>>       /**
>> @@ -588,7 +602,7 @@ public class FastDatePrinter implements
>>        */
>>       private interface Rule {
>>           /**
>> -         * Returns the estimated lentgh of the result.
>> +         * Returns the estimated length of the result.
>>            *
>>            * @return the estimated length
>>            */
>> @@ -810,8 +824,7 @@ public class FastDatePrinter implements
>>               if (value < 10) {
>>                   buffer.append((char)(value + '0'));
>>               } else {
>> -                buffer.append((char)(value / 10 + '0'));
>> -                buffer.append((char)(value % 10 + '0'));
>> +               appendDigits(buffer, value);
>>               }
>>           }
>>       }
>> @@ -863,8 +876,7 @@ public class FastDatePrinter implements
>>                   for (int i = mSize; --i >= 2; ) {
>>                       buffer.append('0');
>>                   }
>> -                buffer.append((char)(value / 10 + '0'));
>> -                buffer.append((char)(value % 10 + '0'));
>> +                appendDigits(buffer, value);
>>               } else {
>>                   int digits;
>>                   if (value < 1000) {
>> @@ -918,8 +930,7 @@ public class FastDatePrinter implements
>>           @Override
>>           public final void appendTo(final StringBuffer buffer, final int
>> value) {
>>               if (value < 100) {
>> -                buffer.append((char)(value / 10 + '0'));
>> -                buffer.append((char)(value % 10 + '0'));
>> +                appendDigits(buffer, value);
>>               } else {
>>                   buffer.append(Integer.toString(value));
>>               }
>> @@ -960,8 +971,7 @@ public class FastDatePrinter implements
>>            */
>>           @Override
>>           public final void appendTo(final StringBuffer buffer, final int
>> value) {
>> -            buffer.append((char)(value / 10 + '0'));
>> -            buffer.append((char)(value % 10 + '0'));
>> +            appendDigits(buffer, value);
>>           }
>>       }
>>
>> @@ -999,8 +1009,7 @@ public class FastDatePrinter implements
>>            */
>>           @Override
>>           public final void appendTo(final StringBuffer buffer, final int
>> value) {
>> -            buffer.append((char)(value / 10 + '0'));
>> -            buffer.append((char)(value % 10 + '0'));
>> +            appendDigits(buffer, value);
>>           }
>>       }
>>
>> @@ -1121,7 +1130,7 @@ public class FastDatePrinter implements
>>           return value;
>>       }
>>
>> -    /**
>> +       /**
>>        * <p>Inner class to output a time zone name.</p>
>>        */
>>       private static class TimeZoneNameRule implements Rule {
>> @@ -1178,7 +1187,7 @@ public class FastDatePrinter implements
>>           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;
>>
>> @@ -1221,16 +1230,95 @@ public class FastDatePrinter implements
>>               }
>>
>>               final int hours = offset / (60 * 60 * 1000);
>> -            buffer.append((char)(hours / 10 + '0'));
>> -            buffer.append((char)(hours % 10 + '0'));
>> +            appendDigits(buffer, hours);
>>
>>               if (mColon) {
>>                   buffer.append(':');
>>               }
>>
>>               final int minutes = offset / (60 * 1000) - 60 * hours;
>> -            buffer.append((char)(minutes / 10 + '0'));
>> -            buffer.append((char)(minutes % 10 + '0'));
>> +            appendDigits(buffer, minutes);
>> +        }
>> +    }
>> +
>> +    /**
>> +     * <p>Inner class to output a time zone as a number {@code +/-HHMM}
>> +     * or {@code +/-HH:MM}.</p>
>> +     */
>> +    private static class Iso8601_Rule implements Rule {
>> +
>> +       // Sign TwoDigitHours or Z
>> +        static final Iso8601_Rule ISO8601_HOURS = new Iso8601_Rule(3);
>> +       // Sign TwoDigitHours Minutes or Z
>> +        static final Iso8601_Rule ISO8601_HOURS_MINUTES = new
>> Iso8601_Rule(5);
>> +       // Sign TwoDigitHours : Minutes or Z
>> +        static final Iso8601_Rule ISO8601_HOURS_COLON_MINUTES = new
>> Iso8601_Rule(6);
>> +
>> +        static Iso8601_Rule getRule(int tokenLen) {
>> +               switch(tokenLen) {
>> +               case 1:
>> +                       return Iso8601_Rule.ISO8601_HOURS;
>> +               case 2:
>> +                       return Iso8601_Rule.ISO8601_HOURS_MINUTES;
>> +               case 3:
>> +                       return Iso8601_Rule.ISO8601_HOURS_COLON_MINUTES;
>> +               default:
>> +                       throw new IllegalArgumentException("invalid number
>> of X");
>> +               }
>> +       }
>> +
>> +        final int length;
>> +
>> +        /**
>> +         * Constructs an instance of {@code Iso8601_Rule} with the
>> specified properties.
>> +         *
>> +         * @param length The number of characters in output (unless Z is
>> output)
>> +         */
>> +        Iso8601_Rule(final int length) {
>> +               this.length = length;
>> +        }
>> +
>> +        /**
>> +         * {@inheritDoc}
>> +         */
>> +        @Override
>> +        public int estimateLength() {
>> +            return length;
>> +        }
>> +
>> +        /**
>> +         * {@inheritDoc}
>> +         */
>> +        @Override
>> +        public void appendTo(final StringBuffer buffer, final Calendar
>> calendar) {
>> +            int zoneOffset = calendar.get(Calendar.ZONE_OFFSET);
>> +                       if (zoneOffset == 0) {
>> +                buffer.append("Z");
>> +                return;
>> +            }
>> +
>> +            int offset = zoneOffset + calendar.get(Calendar.DST_OFFSET);
>> +
>> +            if (offset < 0) {
>> +                buffer.append('-');
>> +                offset = -offset;
>> +            } else {
>> +                buffer.append('+');
>> +            }
>> +
>> +            final int hours = offset / (60 * 60 * 1000);
>> +            appendDigits(buffer, hours);
>> +
>> +            if (length<5) {
>> +               return;
>> +            }
>> +
>> +            if (length==6) {
>> +                buffer.append(':');
>> +            }
>> +
>> +            final int minutes = offset / (60 * 1000) - 60 * hours;
>> +            appendDigits(buffer, minutes);
>>           }
>>       }
>>
>>
>> Modified:
>> commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/time/FastDateParserTest.java
>> URL:
>> http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/time/FastDateParserTest.java?rev=1668511&r1=1668510&r2=1668511&view=diff
>>
>> ==============================================================================
>> ---
>> commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/time/FastDateParserTest.java
>> (original)
>> +++
>> commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/time/FastDateParserTest.java
>> Mon Mar 23 02:33:41 2015
>> @@ -56,6 +56,7 @@ public class FastDateParserTest {
>>       private static final TimeZone REYKJAVIK =
>> TimeZone.getTimeZone("Atlantic/Reykjavik");
>>       private static final TimeZone NEW_YORK =
>> TimeZone.getTimeZone("America/New_York");
>>       private static final TimeZone GMT = TimeZone.getTimeZone("GMT");
>> +    private static final TimeZone INDIA =
>> TimeZone.getTimeZone("Asia/Calcutta");
>>
>>       private static final Locale SWEDEN = new Locale("sv", "SE");
>>
>> @@ -556,4 +557,63 @@ public class FastDateParserTest {
>>           assertEquals(expected.getTime(), fdp.parse("14MAY2014"));
>>           assertEquals(expected.getTime(), fdp.parse("14May2014"));
>>       }
>> +
>> +       @Test(expected = IllegalArgumentException.class)
>> +       public void test1806Argument() {
>> +               getInstance("XXXX");
>> +       }
>> +
>> +       private static Calendar initializeCalendar(TimeZone tz) {
>> +               Calendar cal = Calendar.getInstance(tz);
>> +               cal.set(Calendar.YEAR, 2001);
>> +               cal.set(Calendar.MONTH, 1); // not daylight savings
>> +               cal.set(Calendar.DAY_OF_MONTH, 4);
>> +               cal.set(Calendar.HOUR_OF_DAY, 12);
>> +               cal.set(Calendar.MINUTE, 8);
>> +               cal.set(Calendar.SECOND, 56);
>> +               cal.set(Calendar.MILLISECOND, 235);
>> +               return cal;
>> +       }
>> +
>> +       private static enum Expected1806 {
>> +               India(INDIA, "+05", "+0530", "+05:30", true),
>> +               Greenwich(GMT, "Z", "Z", "Z", false),
>> +               NewYork(NEW_YORK, "-05", "-0500", "-05:00", false);
>> +
>> +               private Expected1806(TimeZone zone, String one, String
>> two, String three, boolean hasHalfHourOffset) {
>> +                       this.zone = zone;
>> +                       this.one = one;
>> +                       this.two = two;
>> +                       this.three = three;
>> +                       this.offset = hasHalfHourOffset ?30*60*1000 :0;
>> +               }
>> +
>> +               final TimeZone zone;
>> +               final String one;
>> +               final String two;
>> +               final String three;
>> +               final long offset;
>> +       }
>> +
>> +       @Test
>> +       public void test1806() throws ParseException {
>> +               String formatStub = "yyyy-MM-dd'T'HH:mm:ss.SSS";
>> +               String dateStub = "2001-02-04T12:08:56.235";
>> +
>> +               for (Expected1806 trial : Expected1806.values()) {
>> +                       Calendar cal = initializeCalendar(trial.zone);
>> +
>> +                       String message = trial.zone.getDisplayName()+";";
>> +
>> +                       DateParser parser = getInstance(formatStub+"X",
>> trial.zone);
>> +                       assertEquals(message+trial.one,
>> cal.getTime().getTime(),
>> parser.parse(dateStub+trial.one).getTime()-trial.offset);
>> +
>> +                       parser = getInstance(formatStub+"XX", trial.zone);
>> +                       assertEquals(message+trial.two, cal.getTime(),
>> parser.parse(dateStub+trial.two));
>> +
>> +                       parser = getInstance(formatStub+"XXX", trial.zone);
>> +                       assertEquals(message+trial.three, cal.getTime(),
>> parser.parse(dateStub+trial.three));
>> +               }
>> +       }
>> +
>>   }
>>
>> 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=1668511&r1=1668510&r2=1668511&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
>> Mon Mar 23 02:33:41 2015
>> @@ -19,6 +19,7 @@ package org.apache.commons.lang3.time;
>>   import static org.junit.Assert.*;
>>
>>   import java.io.Serializable;
>> +import java.text.ParseException;
>>   import java.text.SimpleDateFormat;
>>   import java.util.Calendar;
>>   import java.util.Date;
>> @@ -39,6 +40,8 @@ public class FastDatePrinterTest {
>>
>>       private static final String YYYY_MM_DD = "yyyy/MM/dd";
>>       private static final TimeZone NEW_YORK =
>> TimeZone.getTimeZone("America/New_York");
>> +    private static final TimeZone GMT = TimeZone.getTimeZone("GMT");
>> +    private static final TimeZone INDIA =
>> TimeZone.getTimeZone("Asia/Calcutta");
>>       private static final Locale SWEDEN = new Locale("sv", "SE");
>>
>>           DatePrinter getInstance(final String format) {
>> @@ -272,4 +275,55 @@ public class FastDatePrinterTest {
>>           FastDateFormat colonFormat = FastDateFormat.getInstance("ZZZ");
>>           assertEquals("+00:00", colonFormat.format(c));
>>       }
>> +
>> +       private static Calendar initializeCalendar(TimeZone tz) {
>> +               Calendar cal = Calendar.getInstance(tz);
>> +               cal.set(Calendar.YEAR, 2001);
>> +               cal.set(Calendar.MONTH, 1); // not daylight savings
>> +               cal.set(Calendar.DAY_OF_MONTH, 4);
>> +               cal.set(Calendar.HOUR_OF_DAY, 12);
>> +               cal.set(Calendar.MINUTE, 8);
>> +               cal.set(Calendar.SECOND, 56);
>> +               cal.set(Calendar.MILLISECOND, 235);
>> +               return cal;
>> +       }
>> +
>> +       @Test(expected = IllegalArgumentException.class)
>> +       public void test1806Argument() {
>> +               getInstance("XXXX");
>> +       }
>> +
>> +       private static enum Expected1806 {
>> +               India(INDIA, "+05", "+0530", "+05:30"), Greenwich(GMT,
>> "Z", "Z", "Z"), NewYork(
>> +                               NEW_YORK, "-05", "-0500", "-05:00");
>> +
>> +               private Expected1806(TimeZone zone, String one, String
>> two, String three) {
>> +                       this.zone = zone;
>> +                       this.one = one;
>> +                       this.two = two;
>> +                       this.three = three;
>> +               }
>> +
>> +               final TimeZone zone;
>> +               final String one;
>> +               final String two;
>> +               final String three;
>> +       }
>> +
>> +
>> +       @Test
>> +       public void test1806() throws ParseException {
>> +               for (Expected1806 trial : Expected1806.values()) {
>> +                       Calendar cal = initializeCalendar(trial.zone);
>> +
>> +                       DatePrinter printer = getInstance("X", trial.zone);
>> +                       assertEquals(trial.one, printer.format(cal));
>> +
>> +                       printer = getInstance("XX", trial.zone);
>> +                       assertEquals(trial.two, printer.format(cal));
>> +
>> +                       printer = getInstance("XXX", trial.zone);
>> +                       assertEquals(trial.three, printer.format(cal));
>> +               }
>> +       }
>>   }
>>
>>
>>
>

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


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

Posted by Benedikt Ritter <br...@apache.org>.
Hello Charles,

2015-03-23 16:08 GMT+01:00 Chas Honton <ch...@honton.org>:

> Benedikt,
>
> I apologize.  Thank you for the reminder.  I will update changes.xml this
> evening (GMT-07).
>
> I will also investigate when LANG-1088 was fixed and update changes.xml
> for that.
>

Thank you! I've already added LANG-1100 and LANG-1101.

Regards,
Benedikt


>
>
> Chas
>
> On Mar 22, 2015, at 11:56 PM, Benedikt Ritter <br...@apache.org> wrote:
>
> Charles, I think I've told you this several times now. Please add issues
> you fix to changes.xml! This is necessary to automatically create release
> notes.
>
> Thank you.
> Benedikt
>
> 2015-03-23 3:33 GMT+01:00 <ch...@apache.org>:
>
>> Author: chas
>> Date: Mon Mar 23 02:33:41 2015
>> New Revision: 1668511
>>
>> URL: http://svn.apache.org/r1668511
>> Log:
>> LANG-1101 FastDateParser and FastDatePrinter support 'X' format
>>
>> Modified:
>>
>> 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/FastDateParserTest.java
>>
>> commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/time/FastDatePrinterTest.java
>>
>> 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=1668511&r1=1668510&r2=1668511&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
>> Mon Mar 23 02:33:41 2015
>> @@ -96,7 +96,10 @@ public class FastDateParser implements D
>>
>>      /**
>>       * <p>Constructs a new FastDateParser.</p>
>> -     *
>> +     *
>> +     * Use {@link FastDateFormat#getInstance(String, TimeZone, Locale)}
>> or another variation of the
>> +     * factory methods of {@link FastDateFormat} to get a cached
>> FastDateParser instance.
>> +        *
>>       * @param pattern non-null {@link java.text.SimpleDateFormat}
>> compatible
>>       *  pattern
>>       * @param timeZone non-null time zone to use
>> @@ -467,13 +470,14 @@ public class FastDateParser implements D
>>           * false, if this field is a constant value
>>           */
>>          abstract boolean addRegex(FastDateParser parser, StringBuilder
>> regex);
>> +
>>      }
>>
>>      /**
>>       * A <code>Pattern</code> to parse the user supplied
>> SimpleDateFormat pattern
>>       */
>>      private static final Pattern formatPattern= Pattern.compile(
>> -
>> "D+|E+|F+|G+|H+|K+|M+|S+|W+|Z+|a+|d+|h+|k+|m+|s+|w+|y+|z+|''|'[^']++(''[^']*+)*+'|[^'A-Za-z]++");
>> +
>> "D+|E+|F+|G+|H+|K+|M+|S+|W+|X+|Z+|a+|d+|h+|k+|m+|s+|w+|y+|z+|''|'[^']++(''[^']*+)*+'|[^'A-Za-z]++");
>>
>>      /**
>>       * Obtain a Strategy given a field from a SimpleDateFormat pattern
>> @@ -524,6 +528,8 @@ public class FastDateParser implements D
>>              return WEEK_OF_YEAR_STRATEGY;
>>          case 'y':
>>              return formatField.length()>2 ?LITERAL_YEAR_STRATEGY
>> :ABBREVIATED_YEAR_STRATEGY;
>> +        case 'X':
>> +               return
>> ISO8601TimeZoneStrategy.getStrategy(formatField.length());
>>          case 'Z':
>>              if (formatField.equals("ZZ")) {
>>                  return ISO_8601_STRATEGY;
>> @@ -834,14 +840,18 @@ public class FastDateParser implements D
>>
>>      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})?))";
>> +       private final String pattern;
>> +
>> +        ISO8601TimeZoneStrategy(String pattern) {
>> +               this.pattern = pattern;
>> +        }
>>
>>          /**
>>           * {@inheritDoc}
>>           */
>>          @Override
>>          boolean addRegex(FastDateParser parser, StringBuilder regex) {
>> -            regex.append(PATTERN);
>> +            regex.append(pattern);
>>              return true;
>>          }
>>
>> @@ -856,6 +866,23 @@ public class FastDateParser implements D
>>                  cal.setTimeZone(TimeZone.getTimeZone("GMT" + value));
>>              }
>>          }
>> +
>> +        private static final Strategy ISO_8601_1_STRATEGY = new
>> ISO8601TimeZoneStrategy("(Z|(?:[+-]\\d{2}))");
>> +        private static final Strategy ISO_8601_2_STRATEGY = new
>> ISO8601TimeZoneStrategy("(Z|(?:[+-]\\d{2}\\d{2}))");
>> +        private static final Strategy ISO_8601_3_STRATEGY = new
>> ISO8601TimeZoneStrategy("(Z|(?:[+-]\\d{2}(?::)\\d{2}))");
>> +
>> +               static Strategy getStrategy(int tokenLen) {
>> +               switch(tokenLen) {
>> +               case 1:
>> +                       return ISO_8601_1_STRATEGY;
>> +               case 2:
>> +                       return ISO_8601_2_STRATEGY;
>> +               case 3:
>> +                       return ISO_8601_3_STRATEGY;
>> +               default:
>> +                       throw new IllegalArgumentException("invalid
>> number of X");
>> +               }
>> +               }
>>      }
>>
>>      private static final Strategy NUMBER_MONTH_STRATEGY = new
>> NumberStrategy(Calendar.MONTH) {
>> @@ -887,5 +914,7 @@ 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();
>> +    private static final Strategy ISO_8601_STRATEGY = new
>> ISO8601TimeZoneStrategy("(Z|(?:[+-]\\d{2}(?::?\\d{2})?))");
>> +
>> +
>>  }
>>
>> 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=1668511&r1=1668510&r2=1668511&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
>> Mon Mar 23 02:33:41 2015
>> @@ -38,7 +38,7 @@ import org.apache.commons.lang3.Validate
>>   * <p>FastDatePrinter is a fast and thread-safe version of
>>   * {@link java.text.SimpleDateFormat}.</p>
>>   *
>> - * <p>To obtain a proxy to a FastDatePrinter, use {@link
>> FastDateFormat#getInstance(String, TimeZone, Locale)}
>> + * <p>To obtain a FastDatePrinter, use {@link
>> FastDateFormat#getInstance(String, TimeZone, Locale)}
>>   * or another variation of the factory methods of {@link
>> FastDateFormat}.</p>
>>   *
>>   * <p>Since FastDatePrinter is thread safe, you can use a static member
>> instance:</p>
>> @@ -64,6 +64,10 @@ import org.apache.commons.lang3.Validate
>>   * ISO 8601 full format time zones (eg. {@code +08:00} or {@code
>> -11:00}).
>>   * This introduces a minor incompatibility with Java 1.4, but at a gain
>> of
>>   * useful functionality.</p>
>> + *
>> + * <p>Starting with JDK7, ISO 8601 support was added using the pattern
>> {@code 'X'}.
>> + * To maintain compatibility, {@code 'ZZ'} will continue to be
>> supported, but using
>> + * one of the {@code 'X'} formats is recommended.
>>   *
>>   * <p>Javadoc cites for the year pattern: <i>For formatting, if the
>> number of
>>   * pattern letters is 2, the year is truncated to 2 digits; otherwise it
>> is
>> @@ -137,6 +141,8 @@ public class FastDatePrinter implements
>>
>>  //-----------------------------------------------------------------------
>>      /**
>>       * <p>Constructs a new FastDatePrinter.</p>
>> +     * Use {@link FastDateFormat#getInstance(String, TimeZone, Locale)}
>> or another variation of the
>> +     * factory methods of {@link FastDateFormat} to get a cached
>> FastDatePrinter instance.
>>       *
>>       * @param pattern  {@link java.text.SimpleDateFormat} compatible
>> pattern
>>       * @param timeZone  non-null time zone to use
>> @@ -265,6 +271,9 @@ public class FastDatePrinter implements
>>              case 'K': // hour in am/pm (0..11)
>>                  rule = selectNumberRule(Calendar.HOUR, tokenLen);
>>                  break;
>> +            case 'X': // ISO 8601
>> +               rule = Iso8601_Rule.getRule(tokenLen);
>> +                break;
>>              case 'z': // time zone (text)
>>                  if (tokenLen >= 4) {
>>                      rule = new TimeZoneNameRule(mTimeZone, mLocale,
>> TimeZone.LONG);
>> @@ -581,6 +590,11 @@ public class FastDatePrinter implements
>>          init();
>>      }
>>
>> +       private static void appendDigits(final StringBuffer buffer, final
>> int value) {
>> +               buffer.append((char)(value / 10 + '0'));
>> +               buffer.append((char)(value % 10 + '0'));
>> +       }
>> +
>>      // Rules
>>
>>  //-----------------------------------------------------------------------
>>      /**
>> @@ -588,7 +602,7 @@ public class FastDatePrinter implements
>>       */
>>      private interface Rule {
>>          /**
>> -         * Returns the estimated lentgh of the result.
>> +         * Returns the estimated length of the result.
>>           *
>>           * @return the estimated length
>>           */
>> @@ -810,8 +824,7 @@ public class FastDatePrinter implements
>>              if (value < 10) {
>>                  buffer.append((char)(value + '0'));
>>              } else {
>> -                buffer.append((char)(value / 10 + '0'));
>> -                buffer.append((char)(value % 10 + '0'));
>> +               appendDigits(buffer, value);
>>              }
>>          }
>>      }
>> @@ -863,8 +876,7 @@ public class FastDatePrinter implements
>>                  for (int i = mSize; --i >= 2; ) {
>>                      buffer.append('0');
>>                  }
>> -                buffer.append((char)(value / 10 + '0'));
>> -                buffer.append((char)(value % 10 + '0'));
>> +                appendDigits(buffer, value);
>>              } else {
>>                  int digits;
>>                  if (value < 1000) {
>> @@ -918,8 +930,7 @@ public class FastDatePrinter implements
>>          @Override
>>          public final void appendTo(final StringBuffer buffer, final int
>> value) {
>>              if (value < 100) {
>> -                buffer.append((char)(value / 10 + '0'));
>> -                buffer.append((char)(value % 10 + '0'));
>> +                appendDigits(buffer, value);
>>              } else {
>>                  buffer.append(Integer.toString(value));
>>              }
>> @@ -960,8 +971,7 @@ public class FastDatePrinter implements
>>           */
>>          @Override
>>          public final void appendTo(final StringBuffer buffer, final int
>> value) {
>> -            buffer.append((char)(value / 10 + '0'));
>> -            buffer.append((char)(value % 10 + '0'));
>> +            appendDigits(buffer, value);
>>          }
>>      }
>>
>> @@ -999,8 +1009,7 @@ public class FastDatePrinter implements
>>           */
>>          @Override
>>          public final void appendTo(final StringBuffer buffer, final int
>> value) {
>> -            buffer.append((char)(value / 10 + '0'));
>> -            buffer.append((char)(value % 10 + '0'));
>> +            appendDigits(buffer, value);
>>          }
>>      }
>>
>> @@ -1121,7 +1130,7 @@ public class FastDatePrinter implements
>>          return value;
>>      }
>>
>> -    /**
>> +       /**
>>       * <p>Inner class to output a time zone name.</p>
>>       */
>>      private static class TimeZoneNameRule implements Rule {
>> @@ -1178,7 +1187,7 @@ public class FastDatePrinter implements
>>          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;
>>
>> @@ -1221,16 +1230,95 @@ public class FastDatePrinter implements
>>              }
>>
>>              final int hours = offset / (60 * 60 * 1000);
>> -            buffer.append((char)(hours / 10 + '0'));
>> -            buffer.append((char)(hours % 10 + '0'));
>> +            appendDigits(buffer, hours);
>>
>>              if (mColon) {
>>                  buffer.append(':');
>>              }
>>
>>              final int minutes = offset / (60 * 1000) - 60 * hours;
>> -            buffer.append((char)(minutes / 10 + '0'));
>> -            buffer.append((char)(minutes % 10 + '0'));
>> +            appendDigits(buffer, minutes);
>> +        }
>> +    }
>> +
>> +    /**
>> +     * <p>Inner class to output a time zone as a number {@code +/-HHMM}
>> +     * or {@code +/-HH:MM}.</p>
>> +     */
>> +    private static class Iso8601_Rule implements Rule {
>> +
>> +       // Sign TwoDigitHours or Z
>> +        static final Iso8601_Rule ISO8601_HOURS = new Iso8601_Rule(3);
>> +       // Sign TwoDigitHours Minutes or Z
>> +        static final Iso8601_Rule ISO8601_HOURS_MINUTES = new
>> Iso8601_Rule(5);
>> +       // Sign TwoDigitHours : Minutes or Z
>> +        static final Iso8601_Rule ISO8601_HOURS_COLON_MINUTES = new
>> Iso8601_Rule(6);
>> +
>> +        static Iso8601_Rule getRule(int tokenLen) {
>> +               switch(tokenLen) {
>> +               case 1:
>> +                       return Iso8601_Rule.ISO8601_HOURS;
>> +               case 2:
>> +                       return Iso8601_Rule.ISO8601_HOURS_MINUTES;
>> +               case 3:
>> +                       return Iso8601_Rule.ISO8601_HOURS_COLON_MINUTES;
>> +               default:
>> +                       throw new IllegalArgumentException("invalid
>> number of X");
>> +               }
>> +       }
>> +
>> +        final int length;
>> +
>> +        /**
>> +         * Constructs an instance of {@code Iso8601_Rule} with the
>> specified properties.
>> +         *
>> +         * @param length The number of characters in output (unless Z is
>> output)
>> +         */
>> +        Iso8601_Rule(final int length) {
>> +               this.length = length;
>> +        }
>> +
>> +        /**
>> +         * {@inheritDoc}
>> +         */
>> +        @Override
>> +        public int estimateLength() {
>> +            return length;
>> +        }
>> +
>> +        /**
>> +         * {@inheritDoc}
>> +         */
>> +        @Override
>> +        public void appendTo(final StringBuffer buffer, final Calendar
>> calendar) {
>> +            int zoneOffset = calendar.get(Calendar.ZONE_OFFSET);
>> +                       if (zoneOffset == 0) {
>> +                buffer.append("Z");
>> +                return;
>> +            }
>> +
>> +            int offset = zoneOffset + calendar.get(Calendar.DST_OFFSET);
>> +
>> +            if (offset < 0) {
>> +                buffer.append('-');
>> +                offset = -offset;
>> +            } else {
>> +                buffer.append('+');
>> +            }
>> +
>> +            final int hours = offset / (60 * 60 * 1000);
>> +            appendDigits(buffer, hours);
>> +
>> +            if (length<5) {
>> +               return;
>> +            }
>> +
>> +            if (length==6) {
>> +                buffer.append(':');
>> +            }
>> +
>> +            final int minutes = offset / (60 * 1000) - 60 * hours;
>> +            appendDigits(buffer, minutes);
>>          }
>>      }
>>
>>
>> Modified:
>> commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/time/FastDateParserTest.java
>> URL:
>> http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/time/FastDateParserTest.java?rev=1668511&r1=1668510&r2=1668511&view=diff
>>
>> ==============================================================================
>> ---
>> commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/time/FastDateParserTest.java
>> (original)
>> +++
>> commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/time/FastDateParserTest.java
>> Mon Mar 23 02:33:41 2015
>> @@ -56,6 +56,7 @@ public class FastDateParserTest {
>>      private static final TimeZone REYKJAVIK =
>> TimeZone.getTimeZone("Atlantic/Reykjavik");
>>      private static final TimeZone NEW_YORK =
>> TimeZone.getTimeZone("America/New_York");
>>      private static final TimeZone GMT = TimeZone.getTimeZone("GMT");
>> +    private static final TimeZone INDIA =
>> TimeZone.getTimeZone("Asia/Calcutta");
>>
>>      private static final Locale SWEDEN = new Locale("sv", "SE");
>>
>> @@ -556,4 +557,63 @@ public class FastDateParserTest {
>>          assertEquals(expected.getTime(), fdp.parse("14MAY2014"));
>>          assertEquals(expected.getTime(), fdp.parse("14May2014"));
>>      }
>> +
>> +       @Test(expected = IllegalArgumentException.class)
>> +       public void test1806Argument() {
>> +               getInstance("XXXX");
>> +       }
>> +
>> +       private static Calendar initializeCalendar(TimeZone tz) {
>> +               Calendar cal = Calendar.getInstance(tz);
>> +               cal.set(Calendar.YEAR, 2001);
>> +               cal.set(Calendar.MONTH, 1); // not daylight savings
>> +               cal.set(Calendar.DAY_OF_MONTH, 4);
>> +               cal.set(Calendar.HOUR_OF_DAY, 12);
>> +               cal.set(Calendar.MINUTE, 8);
>> +               cal.set(Calendar.SECOND, 56);
>> +               cal.set(Calendar.MILLISECOND, 235);
>> +               return cal;
>> +       }
>> +
>> +       private static enum Expected1806 {
>> +               India(INDIA, "+05", "+0530", "+05:30", true),
>> +               Greenwich(GMT, "Z", "Z", "Z", false),
>> +               NewYork(NEW_YORK, "-05", "-0500", "-05:00", false);
>> +
>> +               private Expected1806(TimeZone zone, String one, String
>> two, String three, boolean hasHalfHourOffset) {
>> +                       this.zone = zone;
>> +                       this.one = one;
>> +                       this.two = two;
>> +                       this.three = three;
>> +                       this.offset = hasHalfHourOffset ?30*60*1000 :0;
>> +               }
>> +
>> +               final TimeZone zone;
>> +               final String one;
>> +               final String two;
>> +               final String three;
>> +               final long offset;
>> +       }
>> +
>> +       @Test
>> +       public void test1806() throws ParseException {
>> +               String formatStub = "yyyy-MM-dd'T'HH:mm:ss.SSS";
>> +               String dateStub = "2001-02-04T12:08:56.235";
>> +
>> +               for (Expected1806 trial : Expected1806.values()) {
>> +                       Calendar cal = initializeCalendar(trial.zone);
>> +
>> +                       String message = trial.zone.getDisplayName()+";";
>> +
>> +                       DateParser parser = getInstance(formatStub+"X",
>> trial.zone);
>> +                       assertEquals(message+trial.one,
>> cal.getTime().getTime(),
>> parser.parse(dateStub+trial.one).getTime()-trial.offset);
>> +
>> +                       parser = getInstance(formatStub+"XX", trial.zone);
>> +                       assertEquals(message+trial.two, cal.getTime(),
>> parser.parse(dateStub+trial.two));
>> +
>> +                       parser = getInstance(formatStub+"XXX",
>> trial.zone);
>> +                       assertEquals(message+trial.three, cal.getTime(),
>> parser.parse(dateStub+trial.three));
>> +               }
>> +       }
>> +
>>  }
>>
>> 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=1668511&r1=1668510&r2=1668511&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
>> Mon Mar 23 02:33:41 2015
>> @@ -19,6 +19,7 @@ package org.apache.commons.lang3.time;
>>  import static org.junit.Assert.*;
>>
>>  import java.io.Serializable;
>> +import java.text.ParseException;
>>  import java.text.SimpleDateFormat;
>>  import java.util.Calendar;
>>  import java.util.Date;
>> @@ -39,6 +40,8 @@ public class FastDatePrinterTest {
>>
>>      private static final String YYYY_MM_DD = "yyyy/MM/dd";
>>      private static final TimeZone NEW_YORK =
>> TimeZone.getTimeZone("America/New_York");
>> +    private static final TimeZone GMT = TimeZone.getTimeZone("GMT");
>> +    private static final TimeZone INDIA =
>> TimeZone.getTimeZone("Asia/Calcutta");
>>      private static final Locale SWEDEN = new Locale("sv", "SE");
>>
>>          DatePrinter getInstance(final String format) {
>> @@ -272,4 +275,55 @@ public class FastDatePrinterTest {
>>          FastDateFormat colonFormat = FastDateFormat.getInstance("ZZZ");
>>          assertEquals("+00:00", colonFormat.format(c));
>>      }
>> +
>> +       private static Calendar initializeCalendar(TimeZone tz) {
>> +               Calendar cal = Calendar.getInstance(tz);
>> +               cal.set(Calendar.YEAR, 2001);
>> +               cal.set(Calendar.MONTH, 1); // not daylight savings
>> +               cal.set(Calendar.DAY_OF_MONTH, 4);
>> +               cal.set(Calendar.HOUR_OF_DAY, 12);
>> +               cal.set(Calendar.MINUTE, 8);
>> +               cal.set(Calendar.SECOND, 56);
>> +               cal.set(Calendar.MILLISECOND, 235);
>> +               return cal;
>> +       }
>> +
>> +       @Test(expected = IllegalArgumentException.class)
>> +       public void test1806Argument() {
>> +               getInstance("XXXX");
>> +       }
>> +
>> +       private static enum Expected1806 {
>> +               India(INDIA, "+05", "+0530", "+05:30"), Greenwich(GMT,
>> "Z", "Z", "Z"), NewYork(
>> +                               NEW_YORK, "-05", "-0500", "-05:00");
>> +
>> +               private Expected1806(TimeZone zone, String one, String
>> two, String three) {
>> +                       this.zone = zone;
>> +                       this.one = one;
>> +                       this.two = two;
>> +                       this.three = three;
>> +               }
>> +
>> +               final TimeZone zone;
>> +               final String one;
>> +               final String two;
>> +               final String three;
>> +       }
>> +
>> +
>> +       @Test
>> +       public void test1806() throws ParseException {
>> +               for (Expected1806 trial : Expected1806.values()) {
>> +                       Calendar cal = initializeCalendar(trial.zone);
>> +
>> +                       DatePrinter printer = getInstance("X",
>> trial.zone);
>> +                       assertEquals(trial.one, printer.format(cal));
>> +
>> +                       printer = getInstance("XX", trial.zone);
>> +                       assertEquals(trial.two, printer.format(cal));
>> +
>> +                       printer = getInstance("XXX", trial.zone);
>> +                       assertEquals(trial.three, printer.format(cal));
>> +               }
>> +       }
>>  }
>>
>>
>>
>
>
> --
> http://people.apache.org/~britter/
> http://www.systemoutprintln.de/
> http://twitter.com/BenediktRitter
> http://github.com/britter
>
>


-- 
http://people.apache.org/~britter/
http://www.systemoutprintln.de/
http://twitter.com/BenediktRitter
http://github.com/britter