http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/PrintfGTemplateNumberFormatFactory.java ---------------------------------------------------------------------- diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/PrintfGTemplateNumberFormatFactory.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/PrintfGTemplateNumberFormatFactory.java new file mode 100644 index 0000000..e8d5f2b --- /dev/null +++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/PrintfGTemplateNumberFormatFactory.java @@ -0,0 +1,138 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.freemarker.core.userpkg; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.Locale; + +import org.apache.freemarker.core.Environment; +import org.apache.freemarker.core.model.TemplateModelException; +import org.apache.freemarker.core.model.TemplateNumberModel; +import org.apache.freemarker.core.outputformat.impl.HTMLOutputFormat; +import org.apache.freemarker.core.util._StringUtil; +import org.apache.freemarker.core.valueformat.InvalidFormatParametersException; +import org.apache.freemarker.core.valueformat.TemplateFormatUtil; +import org.apache.freemarker.core.valueformat.TemplateNumberFormat; +import org.apache.freemarker.core.valueformat.TemplateNumberFormatFactory; +import org.apache.freemarker.core.valueformat.UnformattableValueException; + +/** + * Formats like {@code %G} in {@code printf}, with the specified number of significant digits. Also has special + * formatter for HTML output format, where it uses the HTML "sup" element for exponents. + */ +public class PrintfGTemplateNumberFormatFactory extends TemplateNumberFormatFactory { + + public static final PrintfGTemplateNumberFormatFactory INSTANCE = new PrintfGTemplateNumberFormatFactory(); + + private PrintfGTemplateNumberFormatFactory() { + // Defined to decrease visibility + } + + @Override + public TemplateNumberFormat get(String params, Locale locale, Environment env) + throws InvalidFormatParametersException { + Integer significantDigits; + if (!params.isEmpty()) { + try { + significantDigits = Integer.valueOf(params); + } catch (NumberFormatException e) { + throw new InvalidFormatParametersException( + "The format parameter must be an integer, but was (shown quoted) " + + _StringUtil.jQuote(params) + "."); + } + } else { + // Use the default of %G + significantDigits = null; + } + return new PrintfGTemplateNumberFormat(significantDigits, locale); + } + + private static class PrintfGTemplateNumberFormat extends TemplateNumberFormat { + + private final Locale locale; + private final String printfFormat; + + private PrintfGTemplateNumberFormat(Integer significantDigits, Locale locale) { + printfFormat = "%" + (significantDigits != null ? "." + significantDigits : "") + "G"; + this.locale = locale; + } + + @Override + public String formatToPlainText(TemplateNumberModel numberModel) + throws UnformattableValueException, TemplateModelException { + final Number n = TemplateFormatUtil.getNonNullNumber(numberModel); + + // printf %G only accepts Double, BigDecimal and Float + final Number gCompatibleN; + if (n instanceof Double || n instanceof BigDecimal || n instanceof Float) { + gCompatibleN = n; + } else { + if (n instanceof BigInteger) { + gCompatibleN = new BigDecimal((BigInteger) n); + } else if (n instanceof Long) { + gCompatibleN = BigDecimal.valueOf(n.longValue()); + } else { + gCompatibleN = Double.valueOf(n.doubleValue()); + } + } + + return String.format(locale, printfFormat, gCompatibleN); + } + + @Override + public Object format(TemplateNumberModel numberModel) + throws UnformattableValueException, TemplateModelException { + String strResult = formatToPlainText(numberModel); + + int expIdx = strResult.indexOf('E'); + if (expIdx == -1) { + return strResult; + } + + String expStr = strResult.substring(expIdx + 1); + int expSignifNumBegin = 0; + while (expSignifNumBegin < expStr.length() && isExpSignifNumPrefix(expStr.charAt(expSignifNumBegin))) { + expSignifNumBegin++; + } + + return HTMLOutputFormat.INSTANCE.fromMarkup( + strResult.substring(0, expIdx) + + "*10<sup>" + + (expStr.charAt(0) == '-' ? "-" : "") + expStr.substring(expSignifNumBegin) + + "</sup>"); + } + + private boolean isExpSignifNumPrefix(char c) { + return c == '+' || c == '-' || c == '0'; + } + + @Override + public boolean isLocaleBound() { + return true; + } + + @Override + public String getDescription() { + return "printf " + printfFormat; + } + + } + +}
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/PublicAll.java ---------------------------------------------------------------------- diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/PublicAll.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/PublicAll.java new file mode 100644 index 0000000..5767e93 --- /dev/null +++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/PublicAll.java @@ -0,0 +1,24 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.freemarker.core.userpkg; + +public class PublicAll { + +} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/PublicWithMixedConstructors.java ---------------------------------------------------------------------- diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/PublicWithMixedConstructors.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/PublicWithMixedConstructors.java new file mode 100644 index 0000000..e521d75 --- /dev/null +++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/PublicWithMixedConstructors.java @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.freemarker.core.userpkg; + +public class PublicWithMixedConstructors { + + private final String s; + + public PublicWithMixedConstructors(Integer x) { + s = "Integer"; + } + + PublicWithMixedConstructors(int x) { + s = "int"; + } + + public String getS() { + return s; + } + +} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/PublicWithPackageVisibleConstructor.java ---------------------------------------------------------------------- diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/PublicWithPackageVisibleConstructor.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/PublicWithPackageVisibleConstructor.java new file mode 100644 index 0000000..9fdec49 --- /dev/null +++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/PublicWithPackageVisibleConstructor.java @@ -0,0 +1,26 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.freemarker.core.userpkg; + +public class PublicWithPackageVisibleConstructor { + + PublicWithPackageVisibleConstructor() { } + +} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/SeldomEscapedOutputFormat.java ---------------------------------------------------------------------- diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/SeldomEscapedOutputFormat.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/SeldomEscapedOutputFormat.java new file mode 100644 index 0000000..b8cab13 --- /dev/null +++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/SeldomEscapedOutputFormat.java @@ -0,0 +1,71 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.freemarker.core.userpkg; + +import java.io.IOException; +import java.io.Writer; + +import org.apache.freemarker.core.model.TemplateModelException; +import org.apache.freemarker.core.outputformat.CommonMarkupOutputFormat; + +public class SeldomEscapedOutputFormat extends CommonMarkupOutputFormat<TemplateSeldomEscapedOutputModel> { + + public static final SeldomEscapedOutputFormat INSTANCE = new SeldomEscapedOutputFormat(); + + private SeldomEscapedOutputFormat() { + // hide + } + + @Override + public String getName() { + return "seldomEscaped"; + } + + @Override + public String getMimeType() { + return "text/seldomEscaped"; + } + + @Override + public void output(String textToEsc, Writer out) throws IOException, TemplateModelException { + out.write(escapePlainText(textToEsc)); + } + + @Override + public String escapePlainText(String plainTextContent) { + return plainTextContent.replaceAll("(\\.|\\\\)", "\\\\$1"); + } + + @Override + public boolean isLegacyBuiltInBypassed(String builtInName) { + return false; + } + + @Override + public boolean isAutoEscapedByDefault() { + return false; + } + + @Override + protected TemplateSeldomEscapedOutputModel newTemplateMarkupOutputModel( + String plainTextContent, String markupContent) { + return new TemplateSeldomEscapedOutputModel(plainTextContent, markupContent); + } + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/TemplateDummyOutputModel.java ---------------------------------------------------------------------- diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/TemplateDummyOutputModel.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/TemplateDummyOutputModel.java new file mode 100644 index 0000000..c98df53 --- /dev/null +++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/TemplateDummyOutputModel.java @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.freemarker.core.userpkg; + +import org.apache.freemarker.core.outputformat.CommonTemplateMarkupOutputModel; + +public class TemplateDummyOutputModel extends CommonTemplateMarkupOutputModel<TemplateDummyOutputModel> { + + TemplateDummyOutputModel(String plainTextContent, String markupContet) { + super(plainTextContent, markupContet); + } + + @Override + public DummyOutputFormat getOutputFormat() { + return DummyOutputFormat.INSTANCE; + } + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/TemplateSeldomEscapedOutputModel.java ---------------------------------------------------------------------- diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/TemplateSeldomEscapedOutputModel.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/TemplateSeldomEscapedOutputModel.java new file mode 100644 index 0000000..b0a21f7 --- /dev/null +++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/TemplateSeldomEscapedOutputModel.java @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.freemarker.core.userpkg; + +import org.apache.freemarker.core.outputformat.CommonTemplateMarkupOutputModel; + +public class TemplateSeldomEscapedOutputModel extends CommonTemplateMarkupOutputModel<TemplateSeldomEscapedOutputModel> { + + TemplateSeldomEscapedOutputModel(String plainTextContent, String markupContet) { + super(plainTextContent, markupContet); + } + + @Override + public SeldomEscapedOutputFormat getOutputFormat() { + return SeldomEscapedOutputFormat.INSTANCE; + } + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/java/org/apache/freemarker/core/util/DateUtilTest.java ---------------------------------------------------------------------- diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/util/DateUtilTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/util/DateUtilTest.java new file mode 100644 index 0000000..0cd8fc0 --- /dev/null +++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/util/DateUtilTest.java @@ -0,0 +1,1085 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.freemarker.core.util; + +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; +import java.util.TimeZone; + +import javax.xml.datatype.DatatypeConfigurationException; +import javax.xml.datatype.DatatypeFactory; +import javax.xml.datatype.XMLGregorianCalendar; + +import org.apache.freemarker.core.util._DateUtil.CalendarFieldsToDateConverter; +import org.apache.freemarker.core.util._DateUtil.DateParseException; +import org.apache.freemarker.core.util._DateUtil.DateToISO8601CalendarFactory; +import org.apache.freemarker.core.util._DateUtil.TrivialCalendarFieldsToDateConverter; + +import junit.framework.TestCase; + +public class DateUtilTest extends TestCase { + + private final TimeZone originalDefaultTZ = TimeZone.getDefault(); + + @Override + protected void setUp() throws Exception { + TimeZone.setDefault(TimeZone.getTimeZone("Europe/Prague")); + } + + @Override + protected void tearDown() throws Exception { + TimeZone.setDefault(originalDefaultTZ); + } + + private final DateFormat df + = new SimpleDateFormat("G yyyy-MM-dd HH:mm:ss:S Z", Locale.US); + { + df.setTimeZone(_DateUtil.UTC); + } + + private CalendarFieldsToDateConverter cf2dc = new TrivialCalendarFieldsToDateConverter(); + + private DateToISO8601CalendarFactory calendarFactory + = new _DateUtil.TrivialDateToISO8601CalendarFactory(); + + public DateUtilTest(String name) { + super(name); + } + + public void testDateToUTCString() throws ParseException { + assertEquals( + "1998-10-30T15:30:00.512Z", + dateToISO8601UTCDateTimeMSString( + df.parse("AD 1998-10-30 19:30:00:512 +0400"), true)); + assertEquals( + "1998-10-30T15:30:00.5Z", + dateToISO8601UTCDateTimeMSString( + df.parse("AD 1998-10-30 19:30:00:500 +0400"), true)); + assertEquals( + "1998-10-30T15:30:00.51Z", + dateToISO8601UTCDateTimeMSString( + df.parse("AD 1998-10-30 19:30:00:510 +0400"), true)); + assertEquals( + "1998-10-30T15:30:00.1Z", + dateToISO8601UTCDateTimeMSString( + df.parse("AD 1998-10-30 19:30:00:100 +0400"), true)); + assertEquals( + "1998-10-30T15:30:00.01Z", + dateToISO8601UTCDateTimeMSString( + df.parse("AD 1998-10-30 19:30:00:10 +0400"), true)); + assertEquals( + "1998-10-30T15:30:00.001Z", + dateToISO8601UTCDateTimeMSString( + df.parse("AD 1998-10-30 19:30:00:1 +0400"), true)); + assertEquals( + "2000-02-08T06:05:04Z", + dateToISO8601UTCDateTimeMSString( + df.parse("AD 2000-02-08 09:05:04:0 +0300"), true)); + assertEquals( + "0099-02-28T06:15:24Z", + dateToISO8601UTCDateTimeString( + df.parse( + "AD 0099-03-02 09:15:24:0 +0300"), true)); + assertEquals( + "0010-02-28T06:15:24Z", + dateToISO8601UTCDateTimeString( + df.parse("AD 0010-03-02 09:15:24:0 +0300"), true)); + assertEquals( + "0001-02-28T06:15:24Z", + dateToISO8601UTCDateTimeString( + df.parse("AD 0001-03-02 09:15:24:0 +0300"), true)); + assertEquals( + "0000-02-29T06:15:24Z", + dateToISO8601UTCDateTimeString( + df.parse("BC 0001-03-02 09:15:24:0 +0300"), true)); + assertEquals( + "-1-02-28T06:15:24Z", + dateToISO8601UTCDateTimeString( + df.parse("BC 2-03-02 09:15:24:0 +0300"), true)); + assertEquals( + "10000-02-28T06:15:24Z", + dateToISO8601UTCDateTimeString( + df.parse("AD 10000-02-28 09:15:24:0 +0300"), true)); + + Date d = df.parse("AD 1998-10-30 19:30:00:512 +0400"); + assertEquals( + "1998-10-30", + dateToISO8601UTCDateString(d)); + assertEquals( + "15:30:00.512Z", + dateToISO8601UTCTimeMSString(d, true)); + assertEquals( + "15:30:00.512", + dateToISO8601UTCTimeMSString(d, false)); + assertEquals( + "1998-10-30", + dateToISO8601UTCDateString( + new java.sql.Date(d.getTime()))); + assertEquals( + "15:30:00.512Z", + dateToISO8601UTCTimeMSString( + new java.sql.Time(d.getTime()), true)); + } + + public void testLocalTime() throws ParseException { + Date dsum = df.parse("AD 2010-05-09 20:00:00:0 UTC"); + Date dwin = df.parse("AD 2010-01-01 20:00:00:0 UTC"); + + TimeZone tzRome = TimeZone.getTimeZone("Europe/Rome"); + if (tzRome.getOffset(0) == 0) { + throw new RuntimeException( + "Can't get time zone for Europe/Rome!"); + } + assertEquals( + "2010-05-09T22:00:00+02:00", + dateToISO8601DateTimeString(dsum, tzRome)); + assertEquals( + "2010-01-01T21:00:00+01:00", + dateToISO8601DateTimeString(dwin, tzRome)); + assertEquals( + "2010-05-09", + dateToISO8601DateString(dsum, tzRome)); + assertEquals( + "2010-01-01", + dateToISO8601DateString(dwin, tzRome)); + assertEquals( + "22:00:00+02:00", + dateToISO8601TimeString(dsum, tzRome)); + assertEquals( + "21:00:00+01:00", + dateToISO8601TimeString(dwin, tzRome)); + + TimeZone tzNY = TimeZone.getTimeZone("America/New_York"); + if (tzNY.getOffset(0) == 0) { + throw new RuntimeException( + "Can't get time zone for America/New_York!"); + } + assertEquals( + "2010-05-09T16:00:00-04:00", + dateToISO8601DateTimeString(dsum, tzNY)); + assertEquals( + "2010-01-01T15:00:00-05:00", + dateToISO8601DateTimeString(dwin, tzNY)); + assertEquals( + "2010-05-09", + dateToISO8601DateString(dsum, tzNY)); + assertEquals( + "2010-01-01", + dateToISO8601DateString(dwin, tzNY)); + assertEquals( + "16:00:00-04:00", + dateToISO8601TimeString(dsum, tzNY)); + assertEquals( + "15:00:00-05:00", + dateToISO8601TimeString(dwin, tzNY)); + + TimeZone tzFixed = TimeZone.getTimeZone("GMT+02:30"); + assertEquals( + "2010-05-09T22:30:00+02:30", + dateToISO8601DateTimeString(dsum, tzFixed)); + assertEquals( + "2010-01-01T22:30:00+02:30", + dateToISO8601DateTimeString(dwin, tzFixed)); + } + + public void testGetTimeZone() throws Exception { + assertTrue(_DateUtil.getTimeZone("GMT") != _DateUtil.UTC); + assertTrue(_DateUtil.getTimeZone("UT1") != _DateUtil.UTC); + assertEquals(_DateUtil.getTimeZone("UTC"), _DateUtil.UTC); + + assertEquals(_DateUtil.getTimeZone("Europe/Rome"), + TimeZone.getTimeZone("Europe/Rome")); + + assertEquals(_DateUtil.getTimeZone("Iceland"), // GMT and no DST + TimeZone.getTimeZone("Iceland")); + + try { + _DateUtil.getTimeZone("Europe/NoSuch"); + fail(); + } catch (UnrecognizedTimeZoneException e) { + // good + } + } + + public void testTimeOnlyDate() throws UnrecognizedTimeZoneException { + Date t = new Date(0L); + SimpleDateFormat tf = new SimpleDateFormat("HH:mm:ss"); + + tf.setTimeZone(_DateUtil.UTC); + assertEquals("00:00:00", tf.format(t)); + assertEquals("00:00:00", + dateToISO8601UTCTimeString(t, false)); + + TimeZone gmt1 = _DateUtil.getTimeZone("GMT+01"); + tf.setTimeZone(gmt1); + assertEquals("01:00:00", tf.format(t)); + assertEquals("01:00:00+01:00", + dateToISO8601TimeString(t, gmt1)); + } + + public void testAccuracy() throws ParseException { + Date d = df.parse("AD 2000-02-08 09:05:04:250 UTC"); + assertEquals("2000-02-08T09:05:04Z", + dateToISO8601UTCDateTimeString(d, true)); + assertEquals("2000-02-08T09:05:04.25Z", + dateToISO8601String(d, true, true, true, + _DateUtil.ACCURACY_MILLISECONDS, null)); + assertEquals("2000-02-08T09:05:04Z", + dateToISO8601String(d, true, true, true, + _DateUtil.ACCURACY_SECONDS, null)); + assertEquals("2000-02-08T09:05Z", + dateToISO8601String(d, true, true, true, + _DateUtil.ACCURACY_MINUTES, null)); + assertEquals("2000-02-08T09Z", + dateToISO8601String(d, true, true, true, + _DateUtil.ACCURACY_HOURS, null)); + + d = df.parse("AD 1998-10-30 19:30:00:000 +0400"); + assertEquals( + "15:30:00Z", + dateToISO8601UTCTimeMSString(d, true)); + assertEquals( + "15:30:00.000Z", + dateToISO8601UTCTimeMSFString(d, true)); + assertEquals( + "1998-10-30T15:30:00Z", + dateToISO8601UTCDateTimeMSString(d, true)); + assertEquals( + "1998-10-30T15:30:00.000Z", + dateToISO8601UTCDateTimeMSFString(d, true)); + + d = df.parse("AD 1998-10-30 19:30:00:100 +0400"); + assertEquals( + "15:30:00.1Z", + dateToISO8601UTCTimeMSString(d, true)); + assertEquals( + "15:30:00.100Z", + dateToISO8601UTCTimeMSFString(d, true)); + assertEquals( + "1998-10-30T15:30:00.1Z", + dateToISO8601UTCDateTimeMSString(d, true)); + assertEquals( + "1998-10-30T15:30:00.100Z", + dateToISO8601UTCDateTimeMSFString(d, true)); + + d = df.parse("AD 1998-10-30 19:30:00:010 +0400"); + assertEquals( + "15:30:00.01Z", + dateToISO8601UTCTimeMSString(d, true)); + assertEquals( + "15:30:00.010Z", + dateToISO8601UTCTimeMSFString(d, true)); + assertEquals( + "1998-10-30T15:30:00.01Z", + dateToISO8601UTCDateTimeMSString(d, true)); + assertEquals( + "1998-10-30T15:30:00.010Z", + dateToISO8601UTCDateTimeMSFString(d, true)); + + d = df.parse("AD 1998-10-30 19:30:00:001 +0400"); + assertEquals( + "15:30:00.001Z", + dateToISO8601UTCTimeMSString(d, true)); + assertEquals( + "15:30:00.001Z", + dateToISO8601UTCTimeMSFString(d, true)); + assertEquals( + "1998-10-30T15:30:00.001Z", + dateToISO8601UTCDateTimeMSString(d, true)); + assertEquals( + "1998-10-30T15:30:00.001Z", + dateToISO8601UTCDateTimeMSFString(d, true)); + } + + public void testXSFormatISODeviations() throws ParseException, UnrecognizedTimeZoneException { + Date dsum = df.parse("AD 2010-05-09 20:00:00:0 UTC"); + Date dwin = df.parse("AD 2010-01-01 20:00:00:0 UTC"); + + TimeZone tzRome = _DateUtil.getTimeZone("Europe/Rome"); + + assertEquals( + "2010-01-01T21:00:00+01:00", + _DateUtil.dateToXSString(dwin, true, true, true, _DateUtil.ACCURACY_SECONDS, tzRome, calendarFactory)); + assertEquals( + "2010-05-09T22:00:00+02:00", + _DateUtil.dateToXSString(dsum, true, true, true, _DateUtil.ACCURACY_SECONDS, tzRome, calendarFactory)); + assertEquals( + "2010-01-01+01:00", // ISO doesn't allow date-only with TZ + _DateUtil.dateToXSString(dwin, true, false, true, _DateUtil.ACCURACY_SECONDS, tzRome, calendarFactory)); + assertEquals( + "2010-05-09+02:00", // ISO doesn't allow date-only with TZ + _DateUtil.dateToXSString(dsum, true, false, true, _DateUtil.ACCURACY_SECONDS, tzRome, calendarFactory)); + assertEquals( + "21:00:00+01:00", + _DateUtil.dateToXSString(dwin, false, true, true, _DateUtil.ACCURACY_SECONDS, tzRome, calendarFactory)); + assertEquals( + "22:00:00+02:00", + _DateUtil.dateToXSString(dsum, false, true, true, _DateUtil.ACCURACY_SECONDS, tzRome, calendarFactory)); + + assertEquals( + "-1-02-29T06:15:24Z", // ISO uses 0 for BC 1 + _DateUtil.dateToXSString( + df.parse("BC 0001-03-02 09:15:24:0 +0300"), + true, true, true, _DateUtil.ACCURACY_SECONDS, _DateUtil.UTC, calendarFactory)); + assertEquals( + "-2-02-28T06:15:24Z", // ISO uses -1 for BC 2 + _DateUtil.dateToXSString( + df.parse("BC 2-03-02 09:15:24:0 +0300"), + true, true, true, _DateUtil.ACCURACY_SECONDS, _DateUtil.UTC, calendarFactory)); + } + + private String dateToISO8601DateTimeString( + Date date, TimeZone tz) { + return dateToISO8601String(date, true, true, true, + _DateUtil.ACCURACY_SECONDS, tz); + } + + private String dateToISO8601UTCDateTimeString( + Date date, boolean offsetPart) { + return dateToISO8601String(date, true, true, offsetPart, + _DateUtil.ACCURACY_SECONDS, _DateUtil.UTC); + } + + private String dateToISO8601UTCDateTimeMSString( + Date date, boolean offsetPart) { + return dateToISO8601String(date, true, true, offsetPart, + _DateUtil.ACCURACY_MILLISECONDS, _DateUtil.UTC); + } + + private String dateToISO8601UTCDateTimeMSFString( + Date date, boolean offsetPart) { + return dateToISO8601String(date, true, true, offsetPart, + _DateUtil.ACCURACY_MILLISECONDS_FORCED, _DateUtil.UTC); + } + + private String dateToISO8601DateString(Date date, TimeZone tz) { + return dateToISO8601String(date, true, false, false, + _DateUtil.ACCURACY_SECONDS, tz); + } + + private String dateToISO8601UTCDateString(Date date) { + return dateToISO8601String(date, true, false, false, + _DateUtil.ACCURACY_SECONDS, _DateUtil.UTC); + } + + private String dateToISO8601TimeString( + Date date, TimeZone tz) { + return dateToISO8601String(date, false, true, true, + _DateUtil.ACCURACY_SECONDS, tz); + } + + private String dateToISO8601UTCTimeString( + Date date, boolean offsetPart) { + return dateToISO8601String(date, false, true, offsetPart, + _DateUtil.ACCURACY_SECONDS, _DateUtil.UTC); + } + + private String dateToISO8601UTCTimeMSString( + Date date, boolean offsetPart) { + return dateToISO8601String(date, false, true, offsetPart, + _DateUtil.ACCURACY_MILLISECONDS, _DateUtil.UTC); + } + + private String dateToISO8601UTCTimeMSFString( + Date date, boolean offsetPart) { + return dateToISO8601String(date, false, true, offsetPart, + _DateUtil.ACCURACY_MILLISECONDS_FORCED, _DateUtil.UTC); + } + + private String dateToISO8601String( + Date date, + boolean datePart, boolean timePart, boolean offsetPart, + int accuracy, + TimeZone timeZone) { + return _DateUtil.dateToISO8601String( + date, + datePart, timePart, offsetPart, + accuracy, + timeZone, + calendarFactory); + } + + public void testParseDate() throws DateParseException { + assertDateParsing( + "AD 1998-10-29 20:00:00:0 +0000", + null, + "1998-10-30+04:00", _DateUtil.UTC); + assertDateParsing( + "AD 1998-10-30 02:00:00:0 +0000", + null, + "1998-10-30-02:00", _DateUtil.UTC); + assertDateParsing( + "AD 1998-10-30 02:00:00:0 +0000", + "1998-10-30", _DateUtil.parseXSTimeZone("-02:00")); + assertDateParsing( + null, + "AD 1998-10-30 02:00:00:0 +0000", + "19981030", _DateUtil.parseXSTimeZone("-02:00")); + assertDateParsing( + "AD 1998-10-30 00:00:00:0 +0000", + null, + "1998-10-30Z", _DateUtil.UTC); + assertDateParsing( + "AD 1998-10-30 00:00:00:0 +0000", + "1998-10-30", _DateUtil.UTC); + assertDateParsing( + null, + "AD 1998-10-30 00:00:00:0 +0000", + "19981030", _DateUtil.UTC); + + assertDateParsing( + "AD 1998-10-29 20:00:00:0 +0000", + null, + "1998-10-30+04:00", _DateUtil.UTC); + assertDateParsing( + "AD 1998-10-30 04:00:00:0 +0000", + null, + "1998-10-30-04:00", _DateUtil.UTC); + assertDateParsing( + "AD 1998-10-30 00:00:00:0 +0000", + null, + "1998-10-30Z", _DateUtil.UTC); + + try { + // XS doesn't have year 0 + assertDateParsing( + "BC 0000-02-05 00:00:00:0 +0000", + null, + "0000-02-03Z", _DateUtil.UTC); + fail(); + } catch (DateParseException e) { + echo(e); + } + assertDateParsing( + null, + "BC 0001-02-05 00:00:00:0 +0000", + "0000-02-03", _DateUtil.UTC); + assertDateParsing( + null, + "BC 0001-02-05 00:00:00:0 +0000", + "00000203", _DateUtil.UTC); + + assertDateParsing( + "BC 0001-02-05 00:00:00:0 +0000", // Julian + "BC 0002-02-05 00:00:00:0 +0000", // Julian + "-0001-02-03", _DateUtil.UTC); // Proleptic Gregorian + assertDateParsing( + null, + "BC 0002-02-05 00:00:00:0 +0000", // Julian + "-00010203", _DateUtil.UTC); // Proleptic Gregorian + + assertDateParsing( + "AD 0001-02-05 00:00:00:0 +0000", // Julian + null, + "0001-02-03Z", _DateUtil.UTC); // Proleptic Gregorian + assertDateParsing( + "AD 0001-02-05 00:00:00:0 +0000", // Julian + "0001-02-03", _DateUtil.UTC); // Proleptic Gregorian + assertDateParsing( + null, + "AD 0001-02-05 00:00:00:0 +0000", // Julian + "00010203", _DateUtil.UTC); // Proleptic Gregorian + assertDateParsing( + "AD 1001-12-07 00:00:00:0 +0000", // Julian + null, + "1001-12-13Z", _DateUtil.UTC); // Proleptic Gregorian + assertDateParsing( + "AD 1001-12-07 00:00:00:0 +0000", // Julian + "1001-12-13", _DateUtil.UTC); // Proleptic Gregorian + + assertDateParsing( + "AD 2006-12-31 00:00:00:0 +0000", + null, + "2006-12-31Z", _DateUtil.UTC); + assertDateParsing( + "AD 2006-12-31 00:00:00:0 +0000", + "2006-12-31", _DateUtil.UTC); + assertDateParsing( + "AD 2006-01-01 00:00:00:0 +0000", + null, + "2006-01-01Z", _DateUtil.UTC); + assertDateParsing( + "AD 2006-01-01 00:00:00:0 +0000", + "2006-01-01", _DateUtil.UTC); + assertDateParsing( + "AD 12006-01-01 00:00:00:0 +0000", + "12006-01-01", _DateUtil.UTC); + assertDateParsing( + null, + "AD 12006-01-01 00:00:00:0 +0000", + "120060101", _DateUtil.UTC); + } + + public void testParseDateMalformed() { + assertDateMalformed("1998-10-30x"); + assertDateMalformed("+1998-10-30"); + assertDateMalformed("1998-10-"); + assertDateMalformed("1998-1-30"); + assertDateMalformed("1998-10-30+01"); + assertDateMalformed("1998-00-01"); + assertDateMalformed("1998-13-01"); + assertDateMalformed("1998-10-00"); + assertDateMalformed("1998-10-32"); + assertDateMalformed("1998-02-31"); + + assertISO8601DateMalformed("2100103"); + assertISO8601DateMalformed("210-01-03"); + assertISO8601DateMalformed("2012-0301"); + assertISO8601DateMalformed("201203-01"); + assertISO8601DateMalformed("2012-01-01+01:00"); + } + + public void testParseTime() throws DateParseException { + assertTimeParsing( + "AD 1970-01-01 17:30:05:0 +0000", + "17:30:05", _DateUtil.UTC); + assertTimeParsing( + null, + "AD 1970-01-01 17:30:05:0 +0000", + "173005", _DateUtil.UTC); + assertTimeParsing( + "AD 1970-01-01 07:30:00:100 +0000", + "07:30:00.1", _DateUtil.UTC); + assertTimeParsing( + "AD 1970-01-01 07:30:00:120 +0000", + "07:30:00.12", _DateUtil.UTC); + assertTimeParsing( + "AD 1970-01-01 07:30:00:123 +0000", + "07:30:00.123", _DateUtil.UTC); + assertTimeParsing( + "AD 1970-01-01 07:30:00:123 +0000", + "07:30:00.1235", _DateUtil.UTC); + assertTimeParsing( + "AD 1970-01-01 07:30:00:123 +0000", + "07:30:00.12346", _DateUtil.UTC); + assertTimeParsing( + null, + "AD 1970-01-01 07:30:00:123 +0000", + "073000.12346", _DateUtil.UTC); + assertTimeParsing( + null, + "AD 1970-01-01 07:30:00:123 +0000", + "073000,12346", _DateUtil.UTC); + assertTimeParsing( + "AD 1970-01-01 07:30:00:120 +0000", + "07:30:00.12", _DateUtil.UTC); + assertTimeParsing( + "AD 1970-01-01 07:30:00:500 +0000", + "07:30:00.5", _DateUtil.UTC); + + assertTimeParsing( + "AD 1970-01-01 16:30:05:0 +0000", + "17:30:05+01:00", _DateUtil.UTC); + assertTimeParsing( + null, + "AD 1970-01-01 16:30:05:0 +0000", + "173005+01", _DateUtil.UTC); + assertTimeParsing( + "AD 1970-01-01 19:00:05:0 +0000", + "17:30:05-01:30", _DateUtil.UTC); + assertTimeParsing( + null, + "AD 1970-01-01 19:00:05:0 +0000", + "173005-0130", _DateUtil.UTC); + assertTimeParsing( + "AD 1970-01-01 16:30:05:500 +0000", + "17:30:05.5+01:00", _DateUtil.UTC); + assertTimeParsing( + null, + "AD 1970-01-01 16:30:05:500 +0000", + "173005.5+0100", _DateUtil.UTC); + assertTimeParsing( + null, + "AD 1970-01-01 16:30:05:500 +0000", + "173005.5+01", _DateUtil.UTC); + assertTimeParsing( + null, + "AD 1970-01-01 16:00:00:0 +0000", + "170000+01", _DateUtil.UTC); + assertTimeParsing( + null, + "AD 1970-01-01 16:00:00:0 +0000", + "1700+01", _DateUtil.UTC); + assertTimeParsing( + null, + "AD 1970-01-01 16:00:00:0 +0000", + "17+01", _DateUtil.UTC); + + assertTimeParsing( + "AD 1970-01-01 00:00:00:0 +0000", + "00:00:00", _DateUtil.UTC); + assertTimeParsing( + "AD 1970-01-02 00:00:00:0 +0000", + "24:00:00", _DateUtil.UTC); + assertTimeParsing( + null, + "AD 1970-01-02 00:00:00:0 +0000", + "240000", _DateUtil.UTC); + assertTimeParsing( + null, + "AD 1970-01-02 00:00:00:0 +0000", + "2400", _DateUtil.UTC); + assertTimeParsing( + null, + "AD 1970-01-02 00:00:00:0 +0000", + "24:00", _DateUtil.UTC); + assertTimeParsing( + null, + "AD 1970-01-02 00:00:00:0 +0000", + "24", _DateUtil.UTC); + + assertTimeParsing( + "AD 1970-01-01 23:59:59:999 +0000", + "23:59:59.999", _DateUtil.UTC); + } + + public void testParseTimeMalformed() { + assertTimeMalformed("00:0000"); + assertTimeMalformed("00:00:00-01:60"); + assertTimeMalformed("24:00:01"); + assertTimeMalformed("00:00:61"); + assertTimeMalformed("00:60:00"); + assertTimeMalformed("25:00:00"); + assertTimeMalformed("2:00:00"); + assertTimeMalformed("02:0:00"); + assertTimeMalformed("02:00:0"); + + assertISO8601TimeMalformed("1010101"); + assertISO8601TimeMalformed("10101"); + assertISO8601TimeMalformed("101"); + assertISO8601TimeMalformed("1"); + assertISO8601TimeMalformed("101010-1"); + assertISO8601TimeMalformed("101010-100"); + assertISO8601TimeMalformed("101010-10000"); + assertISO8601TimeMalformed("101010+1"); + assertISO8601TimeMalformed("101010+100"); + assertISO8601TimeMalformed("101010+10000"); + } + + public void testParseDateTime() throws DateParseException { + assertDateTimeParsing( + "AD 1998-10-30 11:30:00:0 +0000", + "1998-10-30T15:30:00+04:00", _DateUtil.UTC); + assertDateTimeParsing( + null, + "AD 1998-10-30 11:30:00:0 +0000", + "19981030T153000+0400", _DateUtil.UTC); + assertDateTimeParsing( + "AD 1998-10-30 11:30:00:500 +0000", + "1998-10-30T15:30:00.5+04:00", _DateUtil.UTC); + assertDateTimeParsing( + "AD 1998-10-30 15:30:00:0 +0000", + "1998-10-30T15:30:00Z", _DateUtil.UTC); + assertDateTimeParsing( + null, + "AD 1998-10-30 15:30:00:0 +0000", + "19981030T1530Z", _DateUtil.UTC); + assertDateTimeParsing( + "AD 1998-10-30 15:30:00:500 +0000", + "1998-10-30T15:30:00.5Z", _DateUtil.UTC); + assertDateTimeParsing( + "AD 1998-10-30 11:30:00:0 +0000", + "1998-10-30T15:30:00+04:00", _DateUtil.UTC); + assertDateTimeParsing( + "AD 1998-10-30 15:30:00:0 +0000", + "1998-10-30T15:30:00Z", _DateUtil.UTC); + assertDateTimeParsing( + "AD 1998-10-30 15:30:00:0 +0000", + "1998-10-30T15:30:00", _DateUtil.UTC); + assertDateTimeParsing( + null, + "AD 1998-10-30 15:30:00:0 +0000", + "1998-10-30T15:30", _DateUtil.UTC); + + assertDateTimeParsing( + "AD 1998-10-29 20:00:00:0 +0000", + "1998-10-30T00:00:00+04:00", _DateUtil.UTC); + assertDateTimeParsing( + "AD 1998-10-30 02:00:00:0 +0000", + "1998-10-30T00:00:00-02:00", _DateUtil.UTC); + assertDateTimeParsing( + "AD 1998-10-30 00:00:00:0 +0000", + "1998-10-30T00:00:00Z", _DateUtil.UTC); + + assertDateTimeParsing( + "AD 1998-10-29 20:00:00:0 +0000", + "1998-10-30T00:00:00+04:00", _DateUtil.UTC); + assertDateTimeParsing( + "AD 1998-10-30 00:00:00:0 +0000", + "1998-10-30T00:00:00Z", _DateUtil.UTC); + assertDateTimeParsing( + null, + "AD 1998-10-30 00:00:00:0 +0000", + "1998-10-30T00:00Z", _DateUtil.UTC); + assertDateTimeParsing( + null, + "AD 1998-10-30 00:00:00:0 +0000", + "1998-10-30T00:00", _DateUtil.UTC); + assertDateTimeParsing( + null, + "AD 1998-10-30 00:00:00:0 +0000", + "19981030T00Z", _DateUtil.UTC); + + // BC years + try { + assertDateTimeParsing( + "", + null, + "0000-02-03T00:00:00Z", _DateUtil.UTC); + fail(); + } catch (DateParseException e) { + echo(e); + } + assertDateTimeParsing( + null, + "BC 0001-02-05 00:00:00:0 +0000", + "0000-02-03T00:00:00Z", _DateUtil.UTC); + + assertDateTimeParsing( + "BC 0001-02-05 00:00:00:0 +0000", // Julian + "BC 0002-02-05 00:00:00:0 +0000", // Julian + "-0001-02-03T00:00:00Z", _DateUtil.UTC); // Proleptic Gregorian + + assertDateTimeParsing( + "AD 0001-02-05 00:00:00:0 +0000", // Julian + "0001-02-03T00:00:00Z", _DateUtil.UTC); // Proleptic Gregorian + assertDateTimeParsing( + "AD 1001-12-07 00:00:00:0 +0000", // Julian + "1001-12-13T00:00:00Z", _DateUtil.UTC); // Proleptic Gregorian + assertDateTimeParsing( + "AD 11001-12-13 00:00:00:0 +0000", + "11001-12-13T00:00:00Z", _DateUtil.UTC); + assertDateTimeParsing( + null, + "AD 11001-12-13 00:00:00:0 +0000", + "110011213T00Z", _DateUtil.UTC); + + assertDateTimeParsing( + "AD 2006-12-31 00:00:00:0 +0000", + "2006-12-31T00:00:00Z", _DateUtil.UTC); + assertDateTimeParsing( + "AD 2006-01-01 00:00:00:0 +0000", + "2006-01-01T00:00:00Z", _DateUtil.UTC); + + assertDateTimeParsing( + "AD 1970-01-01 07:30:00:123 +0000", + "1970-01-01T07:30:00.123", _DateUtil.UTC); + assertDateTimeParsing( + "AD 1970-01-01 07:30:00:123 +0000", + "1970-01-01T07:30:00.1235", _DateUtil.UTC); + assertDateTimeParsing( + "AD 1970-01-01 07:30:00:123 +0000", + "1970-01-01T07:30:00.12346", _DateUtil.UTC); + assertDateTimeParsing( + "AD 1970-01-01 07:30:00:120 +0000", + "1970-01-01T07:30:00.12", _DateUtil.UTC); + assertDateTimeParsing( + "AD 1970-01-01 07:30:00:500 +0000", + "1970-01-01T07:30:00.5", _DateUtil.UTC); + + assertDateTimeParsing( + "AD 1970-01-01 16:30:05:0 +0000", + "1970-01-01T17:30:05+01:00", _DateUtil.UTC); + assertDateTimeParsing( + "AD 1970-01-01 16:30:05:500 +0000", + "1970-01-01T17:30:05.5+01:00", _DateUtil.UTC); + + assertDateTimeParsing( + "AD 1970-01-01 00:00:00:0 +0000", + "1970-01-01T00:00:00", _DateUtil.UTC); + assertDateTimeParsing( + "AD 1970-01-02 00:00:00:0 +0000", + "1970-01-01T24:00:00", _DateUtil.UTC); + + assertDateTimeParsing( + "AD 1970-01-01 23:59:59:999 +0000", + "1970-01-01T23:59:59.999", _DateUtil.UTC); + } + + public void testParseDateTimeMalformed() throws DateParseException { + assertDateTimeMalformed("1998-00-01T00:00:00"); + assertDateTimeMalformed("1998-13-01T00:00:00"); + assertDateTimeMalformed("1998-10-00T00:00:00"); + assertDateTimeMalformed("1998-10-32T00:00:00"); + assertDateTimeMalformed("1998-02-31T00:00:00"); + assertDateTimeMalformed("1970-01-02T24:00:01"); + assertDateTimeMalformed("1970-01-01T00:00:61"); + assertDateTimeMalformed("1970-01-01T00:60:00"); + assertDateTimeMalformed("1970-01-01T25:00:00"); + + assertISO8601DateTimeMalformed("197-01-01T20:00:00"); + } + + public void testParseXSTimeZone() throws DateParseException { + assertEquals(0, + _DateUtil.parseXSTimeZone("Z").getOffset(0)); + assertEquals(0, + _DateUtil.parseXSTimeZone("-00:00").getOffset(0)); + assertEquals(0, + _DateUtil.parseXSTimeZone("+00:00").getOffset(0)); + assertEquals(90 * 60 * 1000, + _DateUtil.parseXSTimeZone("+01:30").getOffset(0)); + assertEquals(-4 * 60 * 60 * 1000, + _DateUtil.parseXSTimeZone("-04:00").getOffset(0)); + assertEquals(((-23 * 60) - 59) * 60 * 1000, + _DateUtil.parseXSTimeZone("-23:59").getOffset(0)); + assertEquals(((23 * 60) + 59) * 60 * 1000, + _DateUtil.parseXSTimeZone("+23:59").getOffset(0)); + } + + public void testParseXSTimeZoneWrong() { + try { + _DateUtil.parseXSTimeZone("04:00").getOffset(0); + fail(); + } catch (DateParseException e) { + echo(e); + } + try { + _DateUtil.parseXSTimeZone("-04:00x").getOffset(0); + fail(); + } catch (DateParseException e) { + echo(e); + } + try { + _DateUtil.parseXSTimeZone("-04").getOffset(0); + fail(); + } catch (DateParseException e) { + echo(e); + } + try { + _DateUtil.parseXSTimeZone("+24:00").getOffset(0); + fail(); + } catch (DateParseException e) { + echo(e); + } + try { + _DateUtil.parseXSTimeZone("-24:00").getOffset(0); + fail(); + } catch (DateParseException e) { + echo(e); + } + try { + _DateUtil.parseXSTimeZone("-01:60").getOffset(0); + fail(); + } catch (DateParseException e) { + echo(e); + } + } + + public void testParseXSDateTimeFTLAndJavax() throws DateParseException { + // Explicit time zone: + assertJavaxAndFTLXSDateTimesSame("2014-01-01T13:35:08Z"); + assertJavaxAndFTLXSDateTimesSame("2014-01-01T13:35:08+02:00"); + + // Default time zone: + assertJavaxAndFTLXSDateTimesSame("2014-01-01T13:35:08"); // winter + assertJavaxAndFTLXSDateTimesSame("2014-07-01T13:35:08"); // summer + + // Proleptic Gregorian + assertJavaxAndFTLXSDateTimesSame("1500-01-01T13:35:08Z"); + assertJavaxAndFTLXSDateTimesSame("0200-01-01T13:35:08Z"); + assertJavaxAndFTLXSDateTimesSame("0001-01-01T00:00:00+05:00"); + + // BC + assertJavaxAndFTLXSDateTimesSame("0001-01-01T13:35:08Z"); + assertJavaxAndFTLXSDateTimesSame("-0001-01-01T13:35:08Z"); + + // Hour 24 + assertJavaxAndFTLXSDateTimesSame("2014-01-01T23:59:59"); + if (isAtLeastJava6()) { // Java 5 has broken parser that doesn't allow 24. + assertJavaxAndFTLXSDateTimesSame("2014-01-31T24:00:00"); + assertJavaxAndFTLXSDateTimesSame("2014-01-01T24:00:00"); + } + assertJavaxAndFTLXSDateTimesSame("2014-01-02T00:00:00"); // same as the previous + assertJavaxAndFTLXSDateTimesSame("2014-02-01T00:00:00"); // same as the previous + + // Under ms + assertJavaxAndFTLXSDateTimesSame("2014-01-01T23:59:59.123456789"); + assertJavaxAndFTLXSDateTimesSame("2014-01-01T23:59:59.1235"); + } + + private boolean isAtLeastJava6() { + try { + Class.forName("java.lang.management.LockInfo"); + } catch (ClassNotFoundException e) { + return false; + } + return true; + } + + private final DatatypeFactory datetypeFactory; + { + try { + datetypeFactory = DatatypeFactory.newInstance(); + } catch (DatatypeConfigurationException e) { + throw new RuntimeException(e); + } + } + + private void assertJavaxAndFTLXSDateTimesSame(String s) throws DateParseException { + XMLGregorianCalendar xgc = datetypeFactory.newXMLGregorianCalendar(s); + Date javaxDate = xgc.toGregorianCalendar().getTime(); + Date ftlDate = _DateUtil.parseXSDateTime(s, TimeZone.getDefault(), cf2dc); + assertEquals(javaxDate, ftlDate); + } + + private void assertDateParsing(String expected, String parsed, TimeZone tz) throws DateParseException { + assertDateParsing(expected, expected, parsed, tz); + } + + private void assertDateParsing(String expectedXS, String expectedISO8601, String parsed, TimeZone tz) + throws DateParseException { + if (expectedXS != null) { + assertEquals( + expectedXS, + df.format(_DateUtil.parseXSDate(parsed, tz, cf2dc))); + } + if (expectedISO8601 != null) { + assertEquals( + expectedISO8601, + df.format(_DateUtil.parseISO8601Date(parsed, tz, cf2dc))); + } + } + + private void assertDateTimeParsing(String expected, String parsed, TimeZone tz) throws DateParseException { + assertDateTimeParsing(expected, expected, parsed, tz); + } + + private void assertDateTimeParsing(String expectedXS, String expectedISO8601, String parsed, TimeZone tz) + throws DateParseException { + if (expectedXS != null) { + assertEquals( + expectedXS, + df.format(_DateUtil.parseXSDateTime(parsed, tz, cf2dc))); + } + if (expectedISO8601 != null) { + assertEquals( + expectedISO8601, + df.format(_DateUtil.parseISO8601DateTime(parsed, tz, cf2dc))); + } + } + + private void assertTimeParsing(String expected, String parsed, TimeZone tz) throws DateParseException { + assertTimeParsing(expected, expected, parsed, tz); + } + + private void assertTimeParsing(String expectedXS, String expectedISO8601, String parsed, TimeZone tz) + throws DateParseException { + if (expectedXS != null) { + assertEquals( + expectedXS, + df.format(_DateUtil.parseXSTime(parsed, tz, cf2dc))); + } + if (expectedISO8601 != null) { + assertEquals( + expectedISO8601, + df.format(_DateUtil.parseISO8601Time(parsed, tz, cf2dc))); + } + } + + private void assertDateMalformed(String parsed) { + try { + _DateUtil.parseXSDate(parsed, _DateUtil.UTC, cf2dc); + fail(); + } catch (DateParseException e) { + // Expected + echo(e); + } + try { + _DateUtil.parseISO8601Date(parsed, _DateUtil.UTC, cf2dc); + fail(); + } catch (DateParseException e) { + // Expected + echo(e); + } + } + + private void assertTimeMalformed(String parsed) { + try { + _DateUtil.parseXSTime(parsed, _DateUtil.UTC, cf2dc); + fail(); + } catch (DateParseException e) { + // Expected + echo(e); + } + try { + _DateUtil.parseISO8601Time(parsed, _DateUtil.UTC, cf2dc); + fail(); + } catch (DateParseException e) { + // Expected + echo(e); + } + } + + private void assertDateTimeMalformed(String parsed) { + try { + _DateUtil.parseXSDateTime(parsed, _DateUtil.UTC, cf2dc); + fail(); + } catch (DateParseException e) { + // Expected + echo(e); + } + try { + _DateUtil.parseISO8601DateTime(parsed, _DateUtil.UTC, cf2dc); + fail(); + } catch (DateParseException e) { + // Expected + echo(e); + } + } + + private void assertISO8601DateMalformed(String parsed) { + try { + _DateUtil.parseISO8601Date(parsed, _DateUtil.UTC, cf2dc); + fail(); + } catch (DateParseException e) { + // Expected + echo(e); + } + } + + private void assertISO8601TimeMalformed(String parsed) { + try { + _DateUtil.parseISO8601Time(parsed, _DateUtil.UTC, cf2dc); + fail(); + } catch (DateParseException e) { + // Expected + echo(e); + } + } + + private void assertISO8601DateTimeMalformed(String parsed) { + try { + _DateUtil.parseISO8601DateTime(parsed, _DateUtil.UTC, cf2dc); + fail(); + } catch (DateParseException e) { + // Expected + echo(e); + } + } + + private void echo(@SuppressWarnings("unused") DateParseException e) { + // System.out.println(e); + } + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/java/org/apache/freemarker/core/util/FTLUtilTest.java ---------------------------------------------------------------------- diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/util/FTLUtilTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/util/FTLUtilTest.java new file mode 100644 index 0000000..f1e44f3 --- /dev/null +++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/util/FTLUtilTest.java @@ -0,0 +1,117 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.freemarker.core.util; + +import static junit.framework.TestCase.assertFalse; +import static junit.framework.TestCase.assertNull; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +public class FTLUtilTest { + + @Test + public void testEscapeStringLiteralPart() { + assertEquals("", FTLUtil.escapeStringLiteralPart("")); + assertEquals("abc", FTLUtil.escapeStringLiteralPart("abc")); + assertEquals("{", FTLUtil.escapeStringLiteralPart("{")); + assertEquals("a{b}c", FTLUtil.escapeStringLiteralPart("a{b}c")); + assertEquals("a#b", FTLUtil.escapeStringLiteralPart("a#b")); + assertEquals("a$b", FTLUtil.escapeStringLiteralPart("a$b")); + assertEquals("a#\\{b}c", FTLUtil.escapeStringLiteralPart("a#{b}c")); + assertEquals("a$\\{b}c", FTLUtil.escapeStringLiteralPart("a${b}c")); + assertEquals("a'c\\\"d", FTLUtil.escapeStringLiteralPart("a'c\"d", '"')); + assertEquals("a\\'c\"d", FTLUtil.escapeStringLiteralPart("a'c\"d", '\'')); + assertEquals("a\\'c\"d", FTLUtil.escapeStringLiteralPart("a'c\"d", '\'')); + assertEquals("\\n\\r\\t\\f\\x0002\\\\", FTLUtil.escapeStringLiteralPart("\n\r\t\f\u0002\\")); + assertEquals("\\l\\g\\a", FTLUtil.escapeStringLiteralPart("<>&")); + } + + @Test + public void testEscapeStringLiteralAll() { + assertFTLEsc("", "", "", "", "\"\""); + assertFTLEsc("\'", "\\'", "'", "\\'", "\"'\""); + assertFTLEsc("\"", "\\\"", "\\\"", "\"", "'\"'"); + assertFTLEsc("\"", "\\\"", "\\\"", "\"", "'\"'"); + assertFTLEsc("foo", "foo", "foo", "foo", "\"foo\""); + assertFTLEsc("foo's", "foo\\'s", "foo's", "foo\\'s", "\"foo's\""); + assertFTLEsc("foo \"", "foo \\\"", "foo \\\"", "foo \"", "'foo \"'"); + assertFTLEsc("foo's \"", "foo\\'s \\\"", "foo's \\\"", "foo\\'s \"", "\"foo's \\\"\""); + assertFTLEsc("foo\nb\u0000c", "foo\\nb\\x0000c", "foo\\nb\\x0000c", "foo\\nb\\x0000c", "\"foo\\nb\\x0000c\""); + } + + private void assertFTLEsc(String s, String partAny, String partQuot, String partApos, String quoted) { + assertEquals(partAny, FTLUtil.escapeStringLiteralPart(s)); + assertEquals(partQuot, FTLUtil.escapeStringLiteralPart(s, '\"')); + assertEquals(partApos, FTLUtil.escapeStringLiteralPart(s, '\'')); + assertEquals(quoted, FTLUtil.toStringLiteral(s)); + } + + @Test + public void testUnescapeStringLiteralPart() throws Exception { + assertEquals("", FTLUtil.unescapeStringLiteralPart("")); + assertEquals("1", FTLUtil.unescapeStringLiteralPart("1")); + assertEquals("123", FTLUtil.unescapeStringLiteralPart("123")); + assertEquals("1&2&3", FTLUtil.unescapeStringLiteralPart("1\\a2\\a3")); + assertEquals("&", FTLUtil.unescapeStringLiteralPart("\\a")); + assertEquals("&&&", FTLUtil.unescapeStringLiteralPart("\\a\\a\\a")); + assertEquals( + "\u0000\u0000&\u0000\u0000\u0000\u0000", + FTLUtil.unescapeStringLiteralPart("\\x0000\\x0000\\a\\x0000\\x000\\x00\\x0")); + assertEquals( + "'\"\n\b\u0000c><&{\\", + FTLUtil.unescapeStringLiteralPart("\\'\\\"\\n\\b\\x0000c\\g\\l\\a\\{\\\\")); + } + + @Test + public void testEscapeIdentifier() { + assertNull(FTLUtil.escapeIdentifier(null)); + assertEquals("", FTLUtil.escapeIdentifier("")); + assertEquals("a", FTLUtil.escapeIdentifier("a")); + assertEquals("ab", FTLUtil.escapeIdentifier("ab")); + assertEquals("\\.", FTLUtil.escapeIdentifier(".")); + assertEquals("\\.\\:\\-", FTLUtil.escapeIdentifier(".:-")); + assertEquals("a\\.b", FTLUtil.escapeIdentifier("a.b")); + assertEquals("a\\.b\\:c\\-d", FTLUtil.escapeIdentifier("a.b:c-d")); + } + + @Test + public void testIsNonEscapedIdentifierStart() { + assertTrue(FTLUtil.isNonEscapedIdentifierPart('a')); + assertTrue(FTLUtil.isNonEscapedIdentifierPart('á')); + assertTrue(FTLUtil.isNonEscapedIdentifierPart('1')); + assertFalse(FTLUtil.isNonEscapedIdentifierPart('-')); + assertFalse(FTLUtil.isNonEscapedIdentifierPart(' ')); + assertFalse(FTLUtil.isNonEscapedIdentifierPart('\u0000')); + assertFalse(FTLUtil.isNonEscapedIdentifierPart('\\')); + } + + @Test + public void testisNonEscapedIdentifierStart() { + assertTrue(FTLUtil.isNonEscapedIdentifierStart('a')); + assertTrue(FTLUtil.isNonEscapedIdentifierStart('á')); + assertFalse(FTLUtil.isNonEscapedIdentifierStart('1')); + assertFalse(FTLUtil.isNonEscapedIdentifierStart('-')); + assertFalse(FTLUtil.isNonEscapedIdentifierStart(' ')); + assertFalse(FTLUtil.isNonEscapedIdentifierStart('\u0000')); + assertFalse(FTLUtil.isNonEscapedIdentifierStart('\\')); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/java/org/apache/freemarker/core/util/NumberUtilTest.java ---------------------------------------------------------------------- diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/util/NumberUtilTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/util/NumberUtilTest.java new file mode 100644 index 0000000..d5709da --- /dev/null +++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/util/NumberUtilTest.java @@ -0,0 +1,215 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.freemarker.core.util; + +import java.math.BigDecimal; +import java.math.BigInteger; + +import org.junit.Test; + +import junit.framework.TestCase; + +public class NumberUtilTest extends TestCase { + + @Test + public void testGetSignum() { + assertEquals(1, _NumberUtil.getSignum(Double.valueOf(Double.POSITIVE_INFINITY))); + assertEquals(1, _NumberUtil.getSignum(Double.valueOf(3))); + assertEquals(0, _NumberUtil.getSignum(Double.valueOf(0))); + assertEquals(-1, _NumberUtil.getSignum(Double.valueOf(-3))); + assertEquals(-1, _NumberUtil.getSignum(Double.valueOf(Double.NEGATIVE_INFINITY))); + try { + _NumberUtil.getSignum(Double.valueOf(Double.NaN)); + fail(); + } catch (ArithmeticException e) { + // expected + } + + assertEquals(1, _NumberUtil.getSignum(Float.valueOf(Float.POSITIVE_INFINITY))); + assertEquals(1, _NumberUtil.getSignum(Float.valueOf(3))); + assertEquals(0, _NumberUtil.getSignum(Float.valueOf(0))); + assertEquals(-1, _NumberUtil.getSignum(Float.valueOf(-3))); + assertEquals(-1, _NumberUtil.getSignum(Float.valueOf(Float.NEGATIVE_INFINITY))); + try { + _NumberUtil.getSignum(Float.valueOf(Float.NaN)); + fail(); + } catch (ArithmeticException e) { + // expected + } + + assertEquals(1, _NumberUtil.getSignum(Long.valueOf(3))); + assertEquals(0, _NumberUtil.getSignum(Long.valueOf(0))); + assertEquals(-1, _NumberUtil.getSignum(Long.valueOf(-3))); + + assertEquals(1, _NumberUtil.getSignum(Integer.valueOf(3))); + assertEquals(0, _NumberUtil.getSignum(Integer.valueOf(0))); + assertEquals(-1, _NumberUtil.getSignum(Integer.valueOf(-3))); + + assertEquals(1, _NumberUtil.getSignum(Short.valueOf((short) 3))); + assertEquals(0, _NumberUtil.getSignum(Short.valueOf((short) 0))); + assertEquals(-1, _NumberUtil.getSignum(Short.valueOf((short) -3))); + + assertEquals(1, _NumberUtil.getSignum(Byte.valueOf((byte) 3))); + assertEquals(0, _NumberUtil.getSignum(Byte.valueOf((byte) 0))); + assertEquals(-1, _NumberUtil.getSignum(Byte.valueOf((byte) -3))); + + assertEquals(1, _NumberUtil.getSignum(BigDecimal.valueOf(3))); + assertEquals(0, _NumberUtil.getSignum(BigDecimal.valueOf(0))); + assertEquals(-1, _NumberUtil.getSignum(BigDecimal.valueOf(-3))); + + assertEquals(1, _NumberUtil.getSignum(BigInteger.valueOf(3))); + assertEquals(0, _NumberUtil.getSignum(BigInteger.valueOf(0))); + assertEquals(-1, _NumberUtil.getSignum(BigInteger.valueOf(-3))); + } + + @Test + public void testIsBigDecimalInteger() { + BigDecimal n1 = new BigDecimal("1.125"); + if (n1.precision() != 4 || n1.scale() != 3) { + throw new RuntimeException("Wrong: " + n1); + } + BigDecimal n2 = new BigDecimal("1.125").subtract(new BigDecimal("0.005")); + if (n2.precision() != 4 || n2.scale() != 3) { + throw new RuntimeException("Wrong: " + n2); + } + BigDecimal n3 = new BigDecimal("123"); + BigDecimal n4 = new BigDecimal("6000"); + BigDecimal n5 = new BigDecimal("1.12345").subtract(new BigDecimal("0.12345")); + if (n5.precision() != 6 || n5.scale() != 5) { + throw new RuntimeException("Wrong: " + n5); + } + BigDecimal n6 = new BigDecimal("0"); + BigDecimal n7 = new BigDecimal("0.001").subtract(new BigDecimal("0.001")); + BigDecimal n8 = new BigDecimal("60000.5").subtract(new BigDecimal("0.5")); + BigDecimal n9 = new BigDecimal("6").movePointRight(3).setScale(-3); + + BigDecimal[] ns = new BigDecimal[] { + n1, n2, n3, n4, n5, n6, n7, n8, n9, + n1.negate(), n2.negate(), n3.negate(), n4.negate(), n5.negate(), n6.negate(), n7.negate(), n8.negate(), + n9.negate(), + }; + + for (BigDecimal n : ns) { + assertEquals(n.doubleValue() == n.longValue(), _NumberUtil.isIntegerBigDecimal(n)); + } + + } + + @Test + public void testToIntExcact() { + for (int n : new int[] { Integer.MIN_VALUE, Byte.MIN_VALUE, -1, 0, 1, Byte.MAX_VALUE, Integer.MAX_VALUE }) { + if (n != Integer.MIN_VALUE && n != Integer.MAX_VALUE) { + assertEquals(n, _NumberUtil.toIntExact(Byte.valueOf((byte) n))); + assertEquals(n, _NumberUtil.toIntExact(Short.valueOf((short) n))); + assertEquals(n, _NumberUtil.toIntExact(Float.valueOf(n))); + } + assertEquals(n, _NumberUtil.toIntExact(Integer.valueOf(n))); + assertEquals(n, _NumberUtil.toIntExact(Long.valueOf(n))); + assertEquals(n, _NumberUtil.toIntExact(Double.valueOf(n))); + assertEquals(n, _NumberUtil.toIntExact(BigDecimal.valueOf(n))); + assertEquals(n, _NumberUtil.toIntExact(BigDecimal.valueOf(n * 10L).divide(BigDecimal.TEN))); + assertEquals(n, _NumberUtil.toIntExact(BigInteger.valueOf(n))); + } + + try { + _NumberUtil.toIntExact(Long.valueOf(Integer.MIN_VALUE - 1L)); + fail(); + } catch (ArithmeticException e) { + // Expected + } + try { + _NumberUtil.toIntExact(Long.valueOf(Integer.MAX_VALUE + 1L)); + fail(); + } catch (ArithmeticException e) { + // Expected + } + + try { + _NumberUtil.toIntExact(Float.valueOf(1.00001f)); + fail(); + } catch (ArithmeticException e) { + // Expected + } + try { + _NumberUtil.toIntExact(Float.valueOf(Integer.MIN_VALUE - 129L)); + fail(); + } catch (ArithmeticException e) { + // Expected + } + try { + _NumberUtil.toIntExact(Float.valueOf(Integer.MAX_VALUE)); + fail(); + } catch (ArithmeticException e) { + // Expected + } + + try { + _NumberUtil.toIntExact(Double.valueOf(1.00001)); + fail(); + } catch (ArithmeticException e) { + // Expected + } + try { + _NumberUtil.toIntExact(Double.valueOf(Integer.MIN_VALUE - 1L)); + fail(); + } catch (ArithmeticException e) { + // Expected + } + try { + _NumberUtil.toIntExact(Double.valueOf(Integer.MAX_VALUE + 1L)); + fail(); + } catch (ArithmeticException e) { + // Expected + } + + try { + _NumberUtil.toIntExact(new BigDecimal("100.000001")); + fail(); + } catch (ArithmeticException e) { + // Expected + } + try { + _NumberUtil.toIntExact(BigDecimal.valueOf(Integer.MIN_VALUE - 1L)); + fail(); + } catch (ArithmeticException e) { + // Expected + } + try { + _NumberUtil.toIntExact(BigDecimal.valueOf(Integer.MAX_VALUE + 1L)); + fail(); + } catch (ArithmeticException e) { + // Expected + } + + try { + _NumberUtil.toIntExact(BigInteger.valueOf(Integer.MIN_VALUE - 1L)); + fail(); + } catch (ArithmeticException e) { + // Expected + } + try { + _NumberUtil.toIntExact(BigInteger.valueOf(Integer.MAX_VALUE + 1L)); + fail(); + } catch (ArithmeticException e) { + // Expected + } + } + +}
