diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/main/java/com/healthmarketscience/jackcess/impl/expr/FormatUtil.java | 167 | ||||
-rw-r--r-- | src/test/java/com/healthmarketscience/jackcess/impl/expr/DefaultFunctionsTest.java | 11 |
2 files changed, 102 insertions, 76 deletions
diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/expr/FormatUtil.java b/src/main/java/com/healthmarketscience/jackcess/impl/expr/FormatUtil.java index 34d750a..7f23b4e 100644 --- a/src/main/java/com/healthmarketscience/jackcess/impl/expr/FormatUtil.java +++ b/src/main/java/com/healthmarketscience/jackcess/impl/expr/FormatUtil.java @@ -18,9 +18,7 @@ package com.healthmarketscience.jackcess.impl.expr; import java.math.BigDecimal; import java.text.DecimalFormat; -import java.text.FieldPosition; import java.text.NumberFormat; -import java.text.ParsePosition; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatterBuilder; @@ -892,7 +890,7 @@ public class FormatUtil pendingLiteral.setLength(0); } - private static NumberFormat createCustomNumberFormat( + private static BDFormat createCustomNumberFormat( String[] fmtStrs, NumberFormatter.NotationType[] expTypes, boolean[] hasFmts, int fmtIdx, Args args) { @@ -911,26 +909,29 @@ public class FormatUtil sb.deleteCharAt(++i); } } + } else { + // this was a single, literal single quote + sb.append(SINGLE_QUOTE_CHAR); } fmtStr = sb.toString(); } - return new LiteralNumberFormat(fmtStr); + return new LiteralBDFormat(fmtStr); } NumberFormatter.NotationType expType = expTypes[fmtIdx]; - NumberFormat nf = args._ctx.createDecimalFormat(fmtStr); + DecimalFormat df = args._ctx.createDecimalFormat(fmtStr); - DecimalFormat df = (DecimalFormat)nf; if(df.getMaximumFractionDigits() > 0) { // if the decimal is included in the format, access always shows it df.setDecimalSeparatorAlwaysShown(true); } if(expType != null) { - nf = new NumberFormatter.ScientificFormat(nf, expType); + return new BaseBDFormat( + new NumberFormatter.ScientificFormat(df, expType)); } - return nf; + return new DecimalBDFormat(df); } private static Fmt parseCustomTextFormat(ExprBuf buf, Args args) { @@ -1289,7 +1290,7 @@ public class FormatUtil public Set<Map.Entry<Long,String>> entrySet() { return new AbstractSet<Map.Entry<Long,String>>() { @Override - public int size() { + public int size() { return 2; } @Override @@ -1420,40 +1421,66 @@ public class FormatUtil protected abstract Value formatZero(BigDecimal bd, Args args); } + private static final class CustomGeneralFmt extends BaseCustomNumberFmt + { + private final Value _posVal; + private final Value _negVal; + private final Value _zeroVal; + private final Value _nullVal; + + private CustomGeneralFmt(Value posVal, Value negVal, + Value zeroVal, Value nullVal) { + _posVal = posVal; + _negVal = negVal; + _zeroVal = zeroVal; + _nullVal = nullVal; + } + + @Override + protected Value formatNull(Args args) { + return _nullVal; + } + @Override + protected Value formatPos(BigDecimal bd, Args args) { + return _posVal; + } + @Override + protected Value formatNeg(BigDecimal bd, Args args) { + return _negVal; + } + @Override + protected Value formatZero(BigDecimal bd, Args args) { + return _zeroVal; + } + } + private static final class CustomNumberFmt extends BaseCustomNumberFmt { - private final NumberFormat _posFmt; - private final NumberFormat _negFmt; - private final NumberFormat _zeroFmt; - private final NumberFormat _nullFmt; + private final BDFormat _posFmt; + private final BDFormat _negFmt; + private final BDFormat _zeroFmt; + private final BDFormat _nullFmt; - private CustomNumberFmt(NumberFormat posFmt, NumberFormat negFmt, - NumberFormat zeroFmt, NumberFormat nullFmt) { + private CustomNumberFmt(BDFormat posFmt, BDFormat negFmt, + BDFormat zeroFmt, BDFormat nullFmt) { _posFmt = posFmt; _negFmt = negFmt; _zeroFmt = zeroFmt; _nullFmt = nullFmt; } - private Value formatMaybeZero(BigDecimal bd, NumberFormat fmt) { + private Value formatMaybeZero(BigDecimal bd, BDFormat fmt) { // in theory we want to use the given format. however, if, due to // rounding, we end up with a number equivalent to zero, then we fall // back to the zero format. if we are using scientific notation, // however, then don't worry about this - if(!(fmt instanceof NumberFormatter.ScientificFormat)) { - int maxDecDigits = fmt.getMaximumFractionDigits(); - int mult = ((DecimalFormat)fmt).getMultiplier(); - while(mult > 1) { - ++maxDecDigits; - mult /= 10; - } - if(maxDecDigits < bd.scale()) { + int maxDecDigits = fmt.getMaxDecimalDigits(); + if(maxDecDigits < bd.scale()) { bd = bd.setScale(maxDecDigits, NumberFormatter.ROUND_MODE); - } - } - if(BigDecimal.ZERO.compareTo(bd) == 0) { - // fall back to zero format - fmt = _zeroFmt; + if(BigDecimal.ZERO.compareTo(bd) == 0) { + // fall back to zero format + fmt = _zeroFmt; + } } return ValueSupport.toValue(fmt.format(bd)); @@ -1477,72 +1504,62 @@ public class FormatUtil } } - private static final class CustomGeneralFmt extends BaseCustomNumberFmt + private static abstract class BDFormat { - private final Value _posVal; - private final Value _negVal; - private final Value _zeroVal; - private final Value _nullVal; - - private CustomGeneralFmt(Value posVal, Value negVal, - Value zeroVal, Value nullVal) { - _posVal = posVal; - _negVal = negVal; - _zeroVal = zeroVal; - _nullVal = nullVal; + public int getMaxDecimalDigits() { + return Integer.MAX_VALUE; } - @Override - protected Value formatNull(Args args) { - return _nullVal; - } - @Override - protected Value formatPos(BigDecimal bd, Args args) { - return _posVal; - } - @Override - protected Value formatNeg(BigDecimal bd, Args args) { - return _negVal; - } - @Override - protected Value formatZero(BigDecimal bd, Args args) { - return _zeroVal; - } + public abstract String format(BigDecimal bd); } - private static final class LiteralNumberFormat extends NumberFormat + private static final class LiteralBDFormat extends BDFormat { - private static final long serialVersionUID = 0L; - private final String _str; - private LiteralNumberFormat(String str) { + private LiteralBDFormat(String str) { _str = str; } @Override - public StringBuffer format(Object number, StringBuffer toAppendTo, - FieldPosition pos) - { - return toAppendTo.append(_str); + public String format(BigDecimal bd) { + return _str; } + } - @Override - public StringBuffer format(double number, StringBuffer toAppendTo, - FieldPosition pos) { - throw new UnsupportedOperationException(); + private static class BaseBDFormat extends BDFormat + { + private final NumberFormat _nf; + + private BaseBDFormat(NumberFormat nf) { + _nf = nf; } @Override - public Number parse(String source, ParsePosition parsePosition) { - throw new UnsupportedOperationException(); + public String format(BigDecimal bd) { + return _nf.format(bd); + } + } + + private static final class DecimalBDFormat extends BaseBDFormat + { + private final int _maxDecDigits; + + private DecimalBDFormat(DecimalFormat df) { + super(df); + + int maxDecDigits = df.getMaximumFractionDigits(); + int mult = df.getMultiplier(); + while(mult > 1) { + ++maxDecDigits; + mult /= 10; + } + _maxDecDigits = maxDecDigits; } @Override - public StringBuffer format(long number, StringBuffer toAppendTo, - FieldPosition pos) { - throw new UnsupportedOperationException(); + public int getMaxDecimalDigits() { + return _maxDecDigits; } } - } diff --git a/src/test/java/com/healthmarketscience/jackcess/impl/expr/DefaultFunctionsTest.java b/src/test/java/com/healthmarketscience/jackcess/impl/expr/DefaultFunctionsTest.java index 7275fb2..b25f150 100644 --- a/src/test/java/com/healthmarketscience/jackcess/impl/expr/DefaultFunctionsTest.java +++ b/src/test/java/com/healthmarketscience/jackcess/impl/expr/DefaultFunctionsTest.java @@ -333,6 +333,7 @@ public class DefaultFunctionsTest extends TestCase public void testCustomFormat() throws Exception { assertEval("07:00 a", "=Format(#01/10/2003 7:00:00 AM#, 'hh:nn a/p')"); + assertEval("07:00 p", "=Format(#01/10/2003 7:00:00 PM#, 'hh:nn a/p')"); assertEval("07:00 a 6 2", "=Format(#01/10/2003 7:00:00 AM#, 'hh:nn a/p w ww')"); assertEval("07:00 a 4 1", "=Format(#01/10/2003 7:00:00 AM#, 'hh:nn a/p w ww', 3, 3)"); assertEval("1313", "=Format(#01/10/2003 7:13:00 AM#, 'nnnn; foo bar')"); @@ -349,6 +350,8 @@ public class DefaultFunctionsTest extends TestCase "=Format('3.9', 'dddd, yy mmm mm/d, hh:nn:ss AMPM')"); assertEval("9:36:00 PM", "=Format('3.9', 'ttttt')"); + assertEval("9:36:00 PM", + "=Format(3.9, 'ttttt')"); assertEval("foo", "=Format('foo', 'dddd, yy mmm mm d, hh:nn:ss AMPM')"); @@ -359,11 +362,12 @@ public class DefaultFunctionsTest extends TestCase "n", "'0'", "", "Null"); - assertEvalFormat("';\"y\";!\\n;*~\\z[Blue];'", + assertEvalFormat("'\\p;\"y\";!\\n;*~\\z[Blue];'", "foo", "'foo'", "", "''", "y", "True", "n", "'0'", + "p", "'10'", "z", "Null"); assertEvalFormat("'\"p\"#.00#\"blah\"'", @@ -475,6 +479,11 @@ public class DefaultFunctionsTest extends TestCase // "", "0" ); + assertEvalFormat("\"#;n'g;'\"", + "5", "5", + "n'g", "-5", + "'", "0"); + assertEvalFormat("'$0.0#'", "$213.0", "213"); |