Repository: commons-lang Updated Branches: refs/heads/master 03fe88ab7 -> 61579335b
LANG-1154 FastDateFormat APIs that use a StringBuilder Project: http://git-wip-us.apache.org/repos/asf/commons-lang/repo Commit: http://git-wip-us.apache.org/repos/asf/commons-lang/commit/61579335 Tree: http://git-wip-us.apache.org/repos/asf/commons-lang/tree/61579335 Diff: http://git-wip-us.apache.org/repos/asf/commons-lang/diff/61579335 Branch: refs/heads/master Commit: 61579335bcb3da854fc8be82b5e61dc52b5018d3 Parents: 03fe88a Author: Chas Honton <[email protected]> Authored: Mon Jul 13 21:46:14 2015 -0700 Committer: Chas Honton <[email protected]> Committed: Mon Jul 13 21:46:14 2015 -0700 ---------------------------------------------------------------------- src/changes/changes.xml | 1 + .../apache/commons/lang3/time/DatePrinter.java | 44 ++++- .../commons/lang3/time/FastDateFormat.java | 56 +++++- .../commons/lang3/time/FastDatePrinter.java | 172 +++++++++++++------ .../commons/lang3/time/FastDateFormatTest.java | 68 +++++--- .../commons/lang3/time/FastDateParserTest.java | 14 +- .../commons/lang3/time/FastDatePrinterTest.java | 57 +++++- 7 files changed, 327 insertions(+), 85 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/commons-lang/blob/61579335/src/changes/changes.xml ---------------------------------------------------------------------- diff --git a/src/changes/changes.xml b/src/changes/changes.xml index cffa0b3..e6bd030 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -22,6 +22,7 @@ <body> <release version="3.5" date="tba" description="tba"> + <action issue="LANG-1154" type="add" dev="chas" due-to="Gary Gregory">FastDateFormat APIs that use a StringBuilder</action> <action issue="LANG-1149" type="add" dev="chas" due-to="Gregory Zak">Ability to throw checked exceptions without declaring them</action> <action issue="LANG-1002" type="fix" dev="chas" due-to="Michael Osipov">Several predefined ISO FastDateFormats in DateFormatUtils are incorrect</action> <action issue="LANG-1152" type="fix" dev="chas" due-to="Pas Filip">StringIndexOutOfBoundsException or field over-write for large year fields in FastDateParser</action> http://git-wip-us.apache.org/repos/asf/commons-lang/blob/61579335/src/main/java/org/apache/commons/lang3/time/DatePrinter.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/lang3/time/DatePrinter.java b/src/main/java/org/apache/commons/lang3/time/DatePrinter.java index 6808628..a2e97a9 100644 --- a/src/main/java/org/apache/commons/lang3/time/DatePrinter.java +++ b/src/main/java/org/apache/commons/lang3/time/DatePrinter.java @@ -59,23 +59,27 @@ public interface DatePrinter { String format(Calendar calendar); /** - * <p>Formats a milliseond {@code long} value into the + * <p>Formats a millisecond {@code long} value into the * supplied {@code StringBuffer}.</p> + * @deprecated Use {{@link #format(long, Appendable)}. * * @param millis the millisecond value to format * @param buf the buffer to format into * @return the specified string buffer */ + @Deprecated StringBuffer format(long millis, StringBuffer buf); /** * <p>Formats a {@code Date} object into the * supplied {@code StringBuffer} using a {@code GregorianCalendar}.</p> + * @deprecated Use {{@link #format(Date, Appendable)}. * * @param date the date to format * @param buf the buffer to format into * @return the specified string buffer */ + @Deprecated StringBuffer format(Date date, StringBuffer buf); /** @@ -83,13 +87,51 @@ public interface DatePrinter { * The TimeZone set on the Calendar is only used to adjust the time offset. * The TimeZone specified during the construction of the Parser will determine the TimeZone * used in the formatted string. + * @deprecated Use {{@link #format(Calendar, Appendable)}. * * @param calendar the calendar to format * @param buf the buffer to format into * @return the specified string buffer */ + @Deprecated StringBuffer format(Calendar calendar, StringBuffer buf); + /** + * <p>Formats a millisecond {@code long} value into the + * supplied {@code Appendable}.</p> + * + * @param millis the millisecond value to format + * @param buf the buffer to format into + * @return the specified string buffer + * @since 3.5 + */ + <B extends Appendable> B format(long millis, B buf); + + /** + * <p>Formats a {@code Date} object into the + * supplied {@code Appendable} using a {@code GregorianCalendar}.</p> + * + * @param date the date to format + * @param buf the buffer to format into + * @return the specified string buffer + * @since 3.5 + */ + <B extends Appendable> B format(Date date, B buf); + + /** + * <p>Formats a {@code Calendar} object into the supplied {@code Appendable}.</p> + * The TimeZone set on the Calendar is only used to adjust the time offset. + * The TimeZone specified during the construction of the Parser will determine the TimeZone + * used in the formatted string. + * + * @param calendar the calendar to format + * @param buf the buffer to format into + * @return the specified string buffer + * @since 3.5 + */ + <B extends Appendable> B format(Calendar calendar, B buf); + + // Accessors //----------------------------------------------------------------------- /** http://git-wip-us.apache.org/repos/asf/commons-lang/blob/61579335/src/main/java/org/apache/commons/lang3/time/FastDateFormat.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/lang3/time/FastDateFormat.java b/src/main/java/org/apache/commons/lang3/time/FastDateFormat.java index b4cc85d..36d080f 100644 --- a/src/main/java/org/apache/commons/lang3/time/FastDateFormat.java +++ b/src/main/java/org/apache/commons/lang3/time/FastDateFormat.java @@ -399,6 +399,7 @@ public class FastDateFormat extends Format implements DateParser, DatePrinter { /** * <p>Formats a {@code Date}, {@code Calendar} or * {@code Long} (milliseconds) object.</p> + * This method is an implementation of {@link Format#format(Object, StringBuffer, FieldPosition)} * * @param obj the object to format * @param toAppendTo the buffer to append to @@ -407,7 +408,7 @@ public class FastDateFormat extends Format implements DateParser, DatePrinter { */ @Override public StringBuffer format(final Object obj, final StringBuffer toAppendTo, final FieldPosition pos) { - return printer.format(obj, toAppendTo, pos); + return toAppendTo.append(printer.format(obj)); } /** @@ -447,12 +448,14 @@ public class FastDateFormat extends Format implements DateParser, DatePrinter { /** * <p>Formats a millisecond {@code long} value into the * supplied {@code StringBuffer}.</p> + * @deprecated Use {{@link #format(long, Appendable)}. * * @param millis the millisecond value to format * @param buf the buffer to format into * @return the specified string buffer * @since 2.1 */ + @Deprecated @Override public StringBuffer format(final long millis, final StringBuffer buf) { return printer.format(millis, buf); @@ -461,11 +464,13 @@ public class FastDateFormat extends Format implements DateParser, DatePrinter { /** * <p>Formats a {@code Date} object into the * supplied {@code StringBuffer} using a {@code GregorianCalendar}.</p> + * @deprecated Use {{@link #format(Date, Appendable)}. * * @param date the date to format * @param buf the buffer to format into * @return the specified string buffer */ + @Deprecated @Override public StringBuffer format(final Date date, final StringBuffer buf) { return printer.format(date, buf); @@ -474,16 +479,60 @@ public class FastDateFormat extends Format implements DateParser, DatePrinter { /** * <p>Formats a {@code Calendar} object into the * supplied {@code StringBuffer}.</p> + * @deprecated Use {{@link #format(Calendar, Appendable)}. * * @param calendar the calendar to format * @param buf the buffer to format into * @return the specified string buffer */ + @Deprecated @Override public StringBuffer format(final Calendar calendar, final StringBuffer buf) { return printer.format(calendar, buf); } + /** + * <p>Formats a millisecond {@code long} value into the + * supplied {@code StringBuffer}.</p> + * + * @param millis the millisecond value to format + * @param buf the buffer to format into + * @return the specified string buffer + * @since 3.5 + */ + @Override + public <B extends Appendable> B format(final long millis, final B buf) { + return printer.format(millis, buf); + } + + /** + * <p>Formats a {@code Date} object into the + * supplied {@code StringBuffer} using a {@code GregorianCalendar}.</p> + * + * @param date the date to format + * @param buf the buffer to format into + * @return the specified string buffer + * @since 3.5 + */ + @Override + public <B extends Appendable> B format(final Date date, final B buf) { + return printer.format(date, buf); + } + + /** + * <p>Formats a {@code Calendar} object into the + * supplied {@code StringBuffer}.</p> + * + * @param calendar the calendar to format + * @param buf the buffer to format into + * @return the specified string buffer + * @since 3.5 + */ + @Override + public <B extends Appendable> B format(final Calendar calendar, final B buf) { + return printer.format(calendar, buf); + } + // Parsing //----------------------------------------------------------------------- @@ -597,18 +646,17 @@ public class FastDateFormat extends Format implements DateParser, DatePrinter { return "FastDateFormat[" + printer.getPattern() + "," + printer.getLocale() + "," + printer.getTimeZone().getID() + "]"; } - /** * <p>Performs the formatting by applying the rules to the * specified calendar.</p> + * @deprecated Use {{@link #format(Calendar, Appendable) * * @param calendar the calendar to format * @param buf the buffer to format into * @return the specified string buffer */ + @Deprecated protected StringBuffer applyRules(final Calendar calendar, final StringBuffer buf) { return printer.applyRules(calendar, buf); } - - } http://git-wip-us.apache.org/repos/asf/commons-lang/blob/61579335/src/main/java/org/apache/commons/lang3/time/FastDatePrinter.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/lang3/time/FastDatePrinter.java b/src/main/java/org/apache/commons/lang3/time/FastDatePrinter.java index 84bf7e2..14c6d68 100644 --- a/src/main/java/org/apache/commons/lang3/time/FastDatePrinter.java +++ b/src/main/java/org/apache/commons/lang3/time/FastDatePrinter.java @@ -32,6 +32,8 @@ import java.util.TimeZone; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; +import org.apache.commons.lang3.exception.ExceptionUtils; + /** * <p>FastDatePrinter is a fast and thread-safe version of * {@link java.text.SimpleDateFormat}.</p> @@ -387,12 +389,13 @@ public class FastDatePrinter implements DatePrinter, Serializable { /** * <p>Formats a {@code Date}, {@code Calendar} or * {@code Long} (milliseconds) object.</p> - * + * @deprecated Use {{@link #format(Date)}, {{@link #format(Calendar)}, {{@link #format(long)}, or {{@link #format(Object)} * @param obj the object to format * @param toAppendTo the buffer to append to * @param pos the position - ignored * @return the buffer passed in */ + @Deprecated @Override public StringBuffer format(final Object obj, final StringBuffer toAppendTo, final FieldPosition pos) { if (obj instanceof Date) { @@ -407,6 +410,26 @@ public class FastDatePrinter implements DatePrinter, Serializable { } } + /** + * <p>Formats a {@code Date}, {@code Calendar} or + * {@code Long} (milliseconds) object.</p> + * @since 3.5 + * @param obj the object to format + * @return The formatted value. + */ + String format(Object obj) { + if (obj instanceof Date) { + return format((Date) obj); + } else if (obj instanceof Calendar) { + return format((Calendar) obj); + } else if (obj instanceof Long) { + return format(((Long) obj).longValue()); + } else { + throw new IllegalArgumentException("Unknown class: " + + (obj == null ? "<null>" : obj.getClass().getName())); + } + } + /* (non-Javadoc) * @see org.apache.commons.lang3.time.DatePrinter#format(long) */ @@ -423,7 +446,7 @@ public class FastDatePrinter implements DatePrinter, Serializable { * @return a String representation of the given Calendar. */ private String applyRulesToString(final Calendar c) { - return applyRules(c, new StringBuffer(mMaxLengthEstimate)).toString(); + return applyRules(c, new StringBuilder(mMaxLengthEstimate)).toString(); } /** @@ -450,7 +473,7 @@ public class FastDatePrinter implements DatePrinter, Serializable { */ @Override public String format(final Calendar calendar) { - return format(calendar, new StringBuffer(mMaxLengthEstimate)).toString(); + return format(calendar, new StringBuilder(mMaxLengthEstimate)).toString(); } /* (non-Javadoc) @@ -480,6 +503,33 @@ public class FastDatePrinter implements DatePrinter, Serializable { return format(calendar.getTime(), buf); } + /* (non-Javadoc) + * @see org.apache.commons.lang3.time.DatePrinter#format(long, java.lang.Appendable) + */ + @Override + public <B extends Appendable> B format(final long millis, final B buf) { + return format(new Date(millis), buf); + } + + /* (non-Javadoc) + * @see org.apache.commons.lang3.time.DatePrinter#format(java.util.Date, java.lang.Appendable) + */ + @Override + public <B extends Appendable> B format(final Date date, final B buf) { + final Calendar c = newCalendar(); // hard code GregorianCalendar + c.setTime(date); + return applyRules(c, buf); + } + + /* (non-Javadoc) + * @see org.apache.commons.lang3.time.DatePrinter#format(java.util.Calendar, java.lang.Appendable) + */ + @Override + public <B extends Appendable> B format(final Calendar calendar, final B buf) { + // do not pass in calendar directly, this will cause TimeZone of FastDatePrinter to be ignored + return format(calendar.getTime(), buf); + } + /** * <p>Performs the formatting by applying the rules to the * specified calendar.</p> @@ -488,9 +538,13 @@ public class FastDatePrinter implements DatePrinter, Serializable { * @param buf the buffer to format into * @return the specified string buffer */ - protected StringBuffer applyRules(final Calendar calendar, final StringBuffer buf) { - for (final Rule rule : mRules) { - rule.appendTo(buf, calendar); + protected <B extends Appendable> B applyRules(final Calendar calendar, final B buf) { + try { + for (final Rule rule : mRules) { + rule.appendTo(buf, calendar); + } + } catch (IOException ioe) { + ExceptionUtils.rethrow(ioe); } return buf; } @@ -589,16 +643,45 @@ public class FastDatePrinter implements DatePrinter, Serializable { } /** - * Appends digits to the given buffer. - * + * Appends two digits to the given buffer. + * * @param buffer the buffer to append to. * @param value the value to append digits from. */ - private static void appendDigits(final StringBuffer buffer, final int value) { + private static void appendDigits(final Appendable buffer, final int value) throws IOException { buffer.append((char)(value / 10 + '0')); buffer.append((char)(value % 10 + '0')); } + private static final int MAX_DIGITS = 10; // log10(Integer.MAX_VALUE) ~= 9.3 + + /** + * Appends all digits to the given buffer. + * + * @param buffer the buffer to append to. + * @param value the value to append digits from. + */ + private static void appendFullDigits(final Appendable buffer, int value, int minFieldWidth) throws IOException { + // build up decimal representation in reverse + char[] work = new char[MAX_DIGITS]; + int digit = 0; + while(value!=0) { + work[digit++] = (char)(value % 10 + '0'); + value = value / 10; + } + + // pad with zeros + while(digit<minFieldWidth) { + buffer.append('0'); + --minFieldWidth; + } + + // reverse + while(--digit>=0) { + buffer.append(work[digit]); + } + } + // Rules //----------------------------------------------------------------------- /** @@ -615,10 +698,10 @@ public class FastDatePrinter implements DatePrinter, Serializable { /** * Appends the value of the specified calendar to the output buffer based on the rule implementation. * - * @param buffer the output buffer + * @param buf the output buffer * @param calendar calendar to be appended */ - void appendTo(StringBuffer buffer, Calendar calendar); + void appendTo(Appendable buf, Calendar calendar) throws IOException; } /** @@ -631,7 +714,7 @@ public class FastDatePrinter implements DatePrinter, Serializable { * @param buffer the output buffer * @param value the value to be appended */ - void appendTo(StringBuffer buffer, int value); + void appendTo(Appendable buffer, int value) throws IOException; } /** @@ -662,7 +745,7 @@ public class FastDatePrinter implements DatePrinter, Serializable { * {@inheritDoc} */ @Override - public void appendTo(final StringBuffer buffer, final Calendar calendar) { + public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { buffer.append(mValue); } } @@ -695,7 +778,7 @@ public class FastDatePrinter implements DatePrinter, Serializable { * {@inheritDoc} */ @Override - public void appendTo(final StringBuffer buffer, final Calendar calendar) { + public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { buffer.append(mValue); } } @@ -738,7 +821,7 @@ public class FastDatePrinter implements DatePrinter, Serializable { * {@inheritDoc} */ @Override - public void appendTo(final StringBuffer buffer, final Calendar calendar) { + public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { buffer.append(mValues[calendar.get(mField)]); } } @@ -770,7 +853,7 @@ public class FastDatePrinter implements DatePrinter, Serializable { * {@inheritDoc} */ @Override - public void appendTo(final StringBuffer buffer, final Calendar calendar) { + public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { appendTo(buffer, calendar.get(mField)); } @@ -778,13 +861,13 @@ public class FastDatePrinter implements DatePrinter, Serializable { * {@inheritDoc} */ @Override - public final void appendTo(final StringBuffer buffer, final int value) { + public final void appendTo(final Appendable buffer, final int value) throws IOException { if (value < 10) { buffer.append((char)(value + '0')); } else if (value < 100) { appendDigits(buffer, value); } else { - buffer.append(value); + appendFullDigits(buffer, value, 1); } } } @@ -815,7 +898,7 @@ public class FastDatePrinter implements DatePrinter, Serializable { * {@inheritDoc} */ @Override - public void appendTo(final StringBuffer buffer, final Calendar calendar) { + public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { appendTo(buffer, calendar.get(Calendar.MONTH) + 1); } @@ -823,7 +906,7 @@ public class FastDatePrinter implements DatePrinter, Serializable { * {@inheritDoc} */ @Override - public final void appendTo(final StringBuffer buffer, final int value) { + public final void appendTo(final Appendable buffer, final int value) throws IOException { if (value < 10) { buffer.append((char)(value + '0')); } else { @@ -866,7 +949,7 @@ public class FastDatePrinter implements DatePrinter, Serializable { * {@inheritDoc} */ @Override - public void appendTo(final StringBuffer buffer, final Calendar calendar) { + public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { appendTo(buffer, calendar.get(mField)); } @@ -874,23 +957,8 @@ public class FastDatePrinter implements DatePrinter, Serializable { * {@inheritDoc} */ @Override - public final void appendTo(final StringBuffer buffer, int value) { - int first = buffer.length(); - // pad the buffer with adequate zeros - for(int digit = 0; digit<mSize; ++digit) { - buffer.append('0'); - } - // backfill the buffer with non-zero digits - int index = buffer.length(); - for( ; value>0; value /= 10) { - char c= (char)('0' + value % 10); - if(--index<first) { - buffer.insert(first, c); - } - else { - buffer.setCharAt(index, c); - } - } + public final void appendTo(final Appendable buffer, int value) throws IOException { + appendFullDigits(buffer, value, mSize); } } @@ -921,7 +989,7 @@ public class FastDatePrinter implements DatePrinter, Serializable { * {@inheritDoc} */ @Override - public void appendTo(final StringBuffer buffer, final Calendar calendar) { + public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { appendTo(buffer, calendar.get(mField)); } @@ -929,11 +997,11 @@ public class FastDatePrinter implements DatePrinter, Serializable { * {@inheritDoc} */ @Override - public final void appendTo(final StringBuffer buffer, final int value) { + public final void appendTo(final Appendable buffer, final int value) throws IOException { if (value < 100) { appendDigits(buffer, value); } else { - buffer.append(value); + appendFullDigits(buffer, value, 2); } } } @@ -963,7 +1031,7 @@ public class FastDatePrinter implements DatePrinter, Serializable { * {@inheritDoc} */ @Override - public void appendTo(final StringBuffer buffer, final Calendar calendar) { + public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { appendTo(buffer, calendar.get(Calendar.YEAR) % 100); } @@ -971,7 +1039,7 @@ public class FastDatePrinter implements DatePrinter, Serializable { * {@inheritDoc} */ @Override - public final void appendTo(final StringBuffer buffer, final int value) { + public final void appendTo(final Appendable buffer, final int value) throws IOException { appendDigits(buffer, value); } } @@ -1001,7 +1069,7 @@ public class FastDatePrinter implements DatePrinter, Serializable { * {@inheritDoc} */ @Override - public void appendTo(final StringBuffer buffer, final Calendar calendar) { + public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { appendTo(buffer, calendar.get(Calendar.MONTH) + 1); } @@ -1009,7 +1077,7 @@ public class FastDatePrinter implements DatePrinter, Serializable { * {@inheritDoc} */ @Override - public final void appendTo(final StringBuffer buffer, final int value) { + public final void appendTo(final Appendable buffer, final int value) throws IOException { appendDigits(buffer, value); } } @@ -1042,7 +1110,7 @@ public class FastDatePrinter implements DatePrinter, Serializable { * {@inheritDoc} */ @Override - public void appendTo(final StringBuffer buffer, final Calendar calendar) { + public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { int value = calendar.get(Calendar.HOUR); if (value == 0) { value = calendar.getLeastMaximum(Calendar.HOUR) + 1; @@ -1054,7 +1122,7 @@ public class FastDatePrinter implements DatePrinter, Serializable { * {@inheritDoc} */ @Override - public void appendTo(final StringBuffer buffer, final int value) { + public void appendTo(final Appendable buffer, final int value) throws IOException { mRule.appendTo(buffer, value); } } @@ -1087,7 +1155,7 @@ public class FastDatePrinter implements DatePrinter, Serializable { * {@inheritDoc} */ @Override - public void appendTo(final StringBuffer buffer, final Calendar calendar) { + public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { int value = calendar.get(Calendar.HOUR_OF_DAY); if (value == 0) { value = calendar.getMaximum(Calendar.HOUR_OF_DAY) + 1; @@ -1099,7 +1167,7 @@ public class FastDatePrinter implements DatePrinter, Serializable { * {@inheritDoc} */ @Override - public void appendTo(final StringBuffer buffer, final int value) { + public void appendTo(final Appendable buffer, final int value) throws IOException { mRule.appendTo(buffer, value); } } @@ -1170,7 +1238,7 @@ public class FastDatePrinter implements DatePrinter, Serializable { * {@inheritDoc} */ @Override - public void appendTo(final StringBuffer buffer, final Calendar calendar) { + public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { final TimeZone zone = calendar.getTimeZone(); if (calendar.get(Calendar.DST_OFFSET) != 0) { buffer.append(getTimeZoneDisplay(zone, true, mStyle, mLocale)); @@ -1211,7 +1279,7 @@ public class FastDatePrinter implements DatePrinter, Serializable { * {@inheritDoc} */ @Override - public void appendTo(final StringBuffer buffer, final Calendar calendar) { + public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { int offset = calendar.get(Calendar.ZONE_OFFSET) + calendar.get(Calendar.DST_OFFSET); @@ -1290,7 +1358,7 @@ public class FastDatePrinter implements DatePrinter, Serializable { * {@inheritDoc} */ @Override - public void appendTo(final StringBuffer buffer, final Calendar calendar) { + public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { int offset = calendar.get(Calendar.ZONE_OFFSET) + calendar.get(Calendar.DST_OFFSET); if (offset == 0) { buffer.append("Z"); http://git-wip-us.apache.org/repos/asf/commons-lang/blob/61579335/src/test/java/org/apache/commons/lang3/time/FastDateFormatTest.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/commons/lang3/time/FastDateFormatTest.java b/src/test/java/org/apache/commons/lang3/time/FastDateFormatTest.java index 1b69403..564c10c 100644 --- a/src/test/java/org/apache/commons/lang3/time/FastDateFormatTest.java +++ b/src/test/java/org/apache/commons/lang3/time/FastDateFormatTest.java @@ -23,8 +23,9 @@ import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import java.text.FieldPosition; import java.text.Format; -import java.text.ParseException; +import java.text.ParsePosition; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; @@ -33,7 +34,7 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicLongArray; import org.apache.commons.lang3.test.SystemDefaults; import org.apache.commons.lang3.test.SystemDefaultsSwitch; @@ -232,33 +233,43 @@ public class FastDateFormatTest { @Test public void testParseSync() throws InterruptedException { final String pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS"; - final FastDateFormat formatter= FastDateFormat.getInstance(pattern); - - final long sdfTime= measureTime(formatter, new SimpleDateFormat(pattern) { - private static final long serialVersionUID = 1L; // because SimpleDateFormat is serializable + final SimpleDateFormat inner = new SimpleDateFormat(pattern); + final Format sdf= new Format() { + private static final long serialVersionUID = 1L; + + @Override + public StringBuffer format(Object obj, + StringBuffer toAppendTo, + FieldPosition fieldPosition) { + synchronized(this) { + return inner.format(obj, toAppendTo, fieldPosition); + } + } - @Override - public Object parseObject(final String formattedDate) throws ParseException { - synchronized(this) { - return super.parse(formattedDate); - } - } - }); - - final long fdfTime= measureTime(formatter, FastDateFormat.getInstance(pattern)); - - final String times= ">>FastDateFormatTest: FastDateParser:"+fdfTime+" SimpleDateFormat:"+sdfTime; - System.out.println(times); + @Override + public Object parseObject(String source, ParsePosition pos) { + synchronized(this) { + return inner.parseObject(source, pos); + } + } + }; + final AtomicLongArray sdfTime= measureTime(sdf, sdf); + + Format fdf = FastDateFormat.getInstance(pattern); + final AtomicLongArray fdfTime= measureTime(fdf, fdf); + + System.out.println(">>FastDateFormatTest: FastDatePrinter:"+fdfTime.get(0)+" SimpleDateFormat:"+sdfTime.get(0)); + System.out.println(">>FastDateFormatTest: FastDateParser:"+fdfTime.get(1)+" SimpleDateFormat:"+sdfTime.get(1)); } final static private int NTHREADS= 10; final static private int NROUNDS= 10000; - private long measureTime(final Format formatter, final Format parser) throws InterruptedException { + private AtomicLongArray measureTime(final Format printer, final Format parser) throws InterruptedException { final ExecutorService pool = Executors.newFixedThreadPool(NTHREADS); final AtomicInteger failures= new AtomicInteger(0); - final AtomicLong totalElapsed= new AtomicLong(0); - + final AtomicLongArray totalElapsed= new AtomicLongArray(2); + for(int i= 0; i<NTHREADS; ++i) { pool.submit(new Runnable() { @Override @@ -266,10 +277,15 @@ public class FastDateFormatTest { for(int j= 0; j<NROUNDS; ++j) { try { final Date date= new Date(); - final String formattedDate= formatter.format(date); - final long start= System.currentTimeMillis(); + + final long t0= System.currentTimeMillis(); + final String formattedDate= printer.format(date); + totalElapsed.addAndGet(0, System.currentTimeMillis() - t0); + + final long t1 = System.currentTimeMillis(); final Object pd= parser.parseObject(formattedDate); - totalElapsed.addAndGet(System.currentTimeMillis()-start); + totalElapsed.addAndGet(1, System.currentTimeMillis() - t1); + if(!date.equals(pd)) { failures.incrementAndGet(); } @@ -290,9 +306,9 @@ public class FastDateFormatTest { fail("did not complete tasks"); } assertEquals(0, failures.get()); - return totalElapsed.get(); + return totalElapsed; } - + @Test public void testLANG_1152() { TimeZone utc = TimeZone.getTimeZone("UTC"); http://git-wip-us.apache.org/repos/asf/commons-lang/blob/61579335/src/test/java/org/apache/commons/lang3/time/FastDateParserTest.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/commons/lang3/time/FastDateParserTest.java b/src/test/java/org/apache/commons/lang3/time/FastDateParserTest.java index 330935c..4c18e64 100644 --- a/src/test/java/org/apache/commons/lang3/time/FastDateParserTest.java +++ b/src/test/java/org/apache/commons/lang3/time/FastDateParserTest.java @@ -22,6 +22,7 @@ import static org.junit.Assert.assertTrue; import java.io.Serializable; import java.text.ParseException; +import java.text.ParsePosition; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; @@ -666,7 +667,7 @@ public class FastDateParserTest { @Test public void testLang1121() throws ParseException { TimeZone kst = TimeZone.getTimeZone("KST"); - final DateParser fdp = FastDateFormat.getInstance("yyyyMMdd", kst, Locale.KOREA); + final DateParser fdp = getInstance("yyyyMMdd", kst, Locale.KOREA); try { fdp.parse("2015"); @@ -690,4 +691,15 @@ public class FastDateParserTest { actual = fdp.parse("20150429113100"); Assert.assertEquals(expected, actual); } + + @Test + public void testParseOffset() throws ParseException { + DateParser parser = getInstance(YMD_SLASH); + final Date date = parser.parse("Today is 2015/07/04", new ParsePosition(9)); + + final Calendar cal = Calendar.getInstance(); + cal.clear(); + cal.set(2015, Calendar.JULY, 4); + Assert.assertEquals(cal.getTime(), date); + } } http://git-wip-us.apache.org/repos/asf/commons-lang/blob/61579335/src/test/java/org/apache/commons/lang3/time/FastDatePrinterTest.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/commons/lang3/time/FastDatePrinterTest.java b/src/test/java/org/apache/commons/lang3/time/FastDatePrinterTest.java index 74938e8..0727486 100644 --- a/src/test/java/org/apache/commons/lang3/time/FastDatePrinterTest.java +++ b/src/test/java/org/apache/commons/lang3/time/FastDatePrinterTest.java @@ -21,6 +21,7 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import java.io.Serializable; +import java.text.FieldPosition; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Calendar; @@ -30,8 +31,8 @@ import java.util.Locale; import java.util.TimeZone; import org.apache.commons.lang3.SerializationUtils; -import org.apache.commons.lang3.test.SystemDefaultsSwitch; import org.apache.commons.lang3.test.SystemDefaults; +import org.apache.commons.lang3.test.SystemDefaultsSwitch; import org.junit.Rule; import org.junit.Test; @@ -364,4 +365,58 @@ public class FastDatePrinterTest { assertEquals("calendar", "2009-10-16T07:42:16 +0100", value); } } + + @Test + public void testHourFormats() { + Calendar calendar = Calendar.getInstance(); + calendar.clear(); + DatePrinter printer = getInstance("K k H h"); + + calendar.set(Calendar.HOUR_OF_DAY, 0); + assertEquals("0 24 0 12", printer.format(calendar)); + + calendar.set(Calendar.HOUR_OF_DAY, 12); + assertEquals("0 12 12 12", printer.format(calendar)); + + calendar.set(Calendar.HOUR_OF_DAY, 23); + assertEquals("11 23 23 11", printer.format(calendar)); + } + + @Test + public void testStringBufferOptions() { + final DatePrinter format = getInstance("yyyy-MM-dd HH:mm:ss.SSS Z", TimeZone.getTimeZone("GMT")); + Calendar calendar = Calendar.getInstance(); + StringBuffer sb = new StringBuffer(); + String expected = format.format(calendar, sb, new FieldPosition(0)).toString(); + sb.setLength(0); + assertEquals(expected, format.format(calendar, sb).toString()); + sb.setLength(0); + + Date date = calendar.getTime(); + assertEquals(expected, format.format(date, sb, new FieldPosition(0)).toString()); + sb.setLength(0); + assertEquals(expected, format.format(date, sb).toString()); + sb.setLength(0); + + long epoch = date.getTime(); + assertEquals(expected, format.format(epoch, sb, new FieldPosition(0)).toString()); + sb.setLength(0); + assertEquals(expected, format.format(epoch, sb).toString()); + } + + @Test + public void testAppendableOptions() { + final DatePrinter format = getInstance("yyyy-MM-dd HH:mm:ss.SSS Z", TimeZone.getTimeZone("GMT")); + Calendar calendar = Calendar.getInstance(); + StringBuilder sb = new StringBuilder(); + String expected = format.format(calendar, sb).toString(); + sb.setLength(0); + + Date date = calendar.getTime(); + assertEquals(expected, format.format(date, sb).toString()); + sb.setLength(0); + + long epoch = date.getTime(); + assertEquals(expected, format.format(epoch, sb).toString()); + } }
