]> source.dussan.org Git - poi.git/commitdiff
Bug 60369: Adjust pattern to better handle non-ASCII characters in Month-names which...
authorDominik Stadler <centic@apache.org>
Fri, 30 Dec 2016 22:11:55 +0000 (22:11 +0000)
committerDominik Stadler <centic@apache.org>
Fri, 30 Dec 2016 22:11:55 +0000 (22:11 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1776646 13f79535-47bb-0310-9956-ffa450edef68

src/java/org/apache/poi/ss/usermodel/ExcelStyleDateFormatter.java
src/testcases/org/apache/poi/ss/usermodel/TestExcelStyleDateFormatter.java [new file with mode: 0644]

index 5f37bce45696b4589ddc90192f8bb9642f327e30..203aabefa9478795ea41d48464d348b2915b32ba 100644 (file)
@@ -65,7 +65,7 @@ public class ExcelStyleDateFormatter extends SimpleDateFormat {
         setTimeZone(LocaleUtil.getUserTimeZone());
     }
 
-    private double dateToBeFormatted = 0.0;
+    private double dateToBeFormatted;
 
     // no-arg constructor is private because of undefined super call with locale
 
@@ -88,12 +88,12 @@ public class ExcelStyleDateFormatter extends SimpleDateFormat {
      */
     private static String processFormatPattern(String f) {
         String t = f.replaceAll("MMMMM", MMMMM_START_SYMBOL + "MMM" + MMMMM_TRUNCATE_SYMBOL);
-        t = t.replaceAll("\\[H\\]", String.valueOf(H_BRACKET_SYMBOL));
-        t = t.replaceAll("\\[HH\\]", String.valueOf(HH_BRACKET_SYMBOL));
-        t = t.replaceAll("\\[m\\]", String.valueOf(M_BRACKET_SYMBOL));
-        t = t.replaceAll("\\[mm\\]", String.valueOf(MM_BRACKET_SYMBOL));
-        t = t.replaceAll("\\[s\\]", String.valueOf(S_BRACKET_SYMBOL));
-        t = t.replaceAll("\\[ss\\]", String.valueOf(SS_BRACKET_SYMBOL));
+        t = t.replaceAll("\\[H]", String.valueOf(H_BRACKET_SYMBOL));
+        t = t.replaceAll("\\[HH]", String.valueOf(HH_BRACKET_SYMBOL));
+        t = t.replaceAll("\\[m]", String.valueOf(M_BRACKET_SYMBOL));
+        t = t.replaceAll("\\[mm]", String.valueOf(MM_BRACKET_SYMBOL));
+        t = t.replaceAll("\\[s]", String.valueOf(S_BRACKET_SYMBOL));
+        t = t.replaceAll("\\[ss]", String.valueOf(SS_BRACKET_SYMBOL));
         t = t.replaceAll("s.000", "s.SSS");
         t = t.replaceAll("s.00", "s." + LL_BRACKET_SYMBOL);
         t = t.replaceAll("s.0", "s." + L_BRACKET_SYMBOL);
@@ -119,7 +119,7 @@ public class ExcelStyleDateFormatter extends SimpleDateFormat {
         // Now handle our special cases
         if (s.indexOf(MMMMM_START_SYMBOL) != -1) {
             s = s.replaceAll(
-                    MMMMM_START_SYMBOL + "(\\w)\\w+" + MMMMM_TRUNCATE_SYMBOL,
+                    MMMMM_START_SYMBOL + "(\\p{L}|\\p{P})[\\p{L}\\p{P}]+" + MMMMM_TRUNCATE_SYMBOL,
                     "$1"
             );
         }
diff --git a/src/testcases/org/apache/poi/ss/usermodel/TestExcelStyleDateFormatter.java b/src/testcases/org/apache/poi/ss/usermodel/TestExcelStyleDateFormatter.java
new file mode 100644 (file)
index 0000000..af5baf2
--- /dev/null
@@ -0,0 +1,160 @@
+/* ====================================================================
+   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.poi.ss.usermodel;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.text.DateFormatSymbols;
+import java.text.FieldPosition;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+import org.apache.poi.util.LocaleUtil;
+import org.junit.Test;
+
+public class TestExcelStyleDateFormatter {
+    private static final String EXCEL_DATE_FORMAT = "MMMMM";
+
+    /**
+     * [Bug 60369] Month format 'MMMMM' issue with TEXT-formula and Java 8
+     */
+    @Test
+    public void test60369() throws ParseException {
+        // Setting up the locale to be tested together with a list of asserted unicode-formatted results and put them in a map.
+        Locale germanLocale = Locale.GERMAN;
+        List<String> germanResultList = Arrays.asList("\u004a", "\u0046", "\u004d", "\u0041", "\u004d",
+                "\u004a", "\u004a", "\u0041", "\u0053", "\u004f", "\u004e", "\u0044");
+
+        Locale russianLocale = new Locale("ru", "RU");
+        List<String> russianResultList = Arrays.asList("\u044f", "\u0444", "\u043c", "\u0430", "\u043c",
+                "\u0438", "\u0438", "\u0430", "\u0441", "\u043e", "\u043d", "\u0434");
+
+        Locale austrianLocale = new Locale("de", "AT");
+        List<String> austrianResultList = Arrays.asList("\u004a", "\u0046", "\u004d", "\u0041", "\u004d",
+                "\u004a", "\u004a", "\u0041", "\u0053", "\u004f", "\u004e", "\u0044");
+
+        Locale englishLocale = Locale.UK;
+        List<String> englishResultList = Arrays.asList("\u004a", "\u0046", "\u004d", "\u0041", "\u004d",
+                "\u004a", "\u004a", "\u0041", "\u0053", "\u004f", "\u004e", "\u0044");
+
+        Locale frenchLocale = Locale.FRENCH;
+        List<String> frenchResultList = Arrays.asList("\u006a", "\u0066", "\u006d", "\u0061", "\u006d",
+                "\u006a", "\u006a", "\u0061", "\u0073", "\u006f", "\u006e", "\u0064");
+
+        Locale chineseLocale = Locale.CHINESE;
+        List<String> chineseResultList = Arrays.asList("\u4e00", "\u4e8c", "\u4e09", "\u56db", "\u4e94",
+                "\u516d", "\u4e03", "\u516b", "\u4e5d", "\u5341", "\u5341", "\u5341");
+
+        Locale turkishLocale = new Locale("tr", "TR");
+        List<String> turkishResultList = Arrays.asList("\u004f", "\u015e", "\u004d", "\u004e", "\u004d",
+                "\u0048", "\u0054", "\u0041", "\u0045", "\u0045", "\u004b", "\u0041");
+
+        Locale hungarianLocale = new Locale("hu", "HU");
+        List<String> hungarianResultList = Arrays.asList("\u006a", "\u0066", "\u006d", "\u00e1", "\u006d",
+                "\u006a", "\u006a", "\u0061", "\u0073", "\u006f", "\u006e", "\u0064");
+
+        Locale indianLocale = new Locale("en", "IN");
+        List<String> indianResultList = Arrays.asList("\u004a", "\u0046", "\u004d", "\u0041", "\u004d",
+                "\u004a", "\u004a", "\u0041", "\u0053", "\u004f", "\u004e", "\u0044");
+
+        Locale indonesianLocale = new Locale("in", "ID");
+        List<String> indonesianResultList = Arrays.asList("\u004a", "\u0046", "\u004d", "\u0041", "\u004d",
+                "\u004a", "\u004a", "\u0041", "\u0053", "\u004f", "\u004e", "\u0044");
+
+
+        Map<Locale, List<String>> testMap = new HashMap<Locale, List<String>>();
+        testMap.put(germanLocale,        germanResultList);
+        testMap.put(russianLocale,        russianResultList);
+        testMap.put(austrianLocale,        austrianResultList);
+        testMap.put(englishLocale,        englishResultList);
+        testMap.put(frenchLocale,        frenchResultList);
+        testMap.put(chineseLocale,        chineseResultList);
+        testMap.put(turkishLocale,        turkishResultList);
+        testMap.put(hungarianLocale,    hungarianResultList);
+        testMap.put(indianLocale,        indianResultList);
+        testMap.put(indonesianLocale,    indonesianResultList);
+
+        // We have to set up dates as well.
+        SimpleDateFormat testDateFormat = new SimpleDateFormat("dd.MM.yyyy", Locale.ROOT);
+        List<Date> testDates = Arrays.asList(
+                testDateFormat.parse("12.01.1980"),
+                testDateFormat.parse("11.02.1995"),
+                testDateFormat.parse("10.03.2045"),
+                testDateFormat.parse("09.04.2016"),
+                testDateFormat.parse("08.05.2017"),
+                testDateFormat.parse("07.06.1945"),
+                testDateFormat.parse("06.07.1998"),
+                testDateFormat.parse("05.08.2099"),
+                testDateFormat.parse("04.09.1988"),
+                testDateFormat.parse("03.10.2023"),
+                testDateFormat.parse("02.11.1978"),
+                testDateFormat.parse("01.12.1890"));
+
+        // Let's iterate over the test setup.
+        for (Locale locale : testMap.keySet()) {
+            //System.err.println("Locale: " + locale);
+            ExcelStyleDateFormatter formatter = new ExcelStyleDateFormatter(EXCEL_DATE_FORMAT, new DateFormatSymbols(locale));
+            for (int i = 0; i < 12; i++) {
+                // Call the method to be tested!
+                String result =
+                        formatter.format(testDates.get(i),
+                                new StringBuffer(),
+                                new FieldPosition(java.text.DateFormat.MONTH_FIELD)).toString();
+                //System.err.println(result +  " - " + getUnicode(result.charAt(0)));
+                assertEquals(getUnicode(testMap.get(locale).get(i).charAt(0)), getUnicode(result.charAt(0)));
+            }
+        }
+    }
+
+    private String getUnicode(char c) {
+        return "\\u" + Integer.toHexString(c | 0x10000).substring(1);
+    }
+
+    @Test
+    public void testConstruct() {
+        assertNotNull(new ExcelStyleDateFormatter(EXCEL_DATE_FORMAT, LocaleUtil.getUserLocale()));
+        assertNotNull(new ExcelStyleDateFormatter(EXCEL_DATE_FORMAT));
+    }
+
+    @Test
+    public void testWithLocale() throws ParseException {
+        Locale before = LocaleUtil.getUserLocale();
+        try {
+            LocaleUtil.setUserLocale(Locale.GERMAN);
+            String dateStr = new ExcelStyleDateFormatter(EXCEL_DATE_FORMAT).format(
+                    new SimpleDateFormat("yyyy-MM-dd", Locale.ROOT).parse("2016-03-26"));
+            assertEquals("M", dateStr);
+        } finally {
+            LocaleUtil.setUserLocale(before);
+        }
+    }
+
+    @Test
+    public void testWithPattern() throws ParseException {
+        String dateStr = new ExcelStyleDateFormatter("yyyy|" + EXCEL_DATE_FORMAT + "|").format(
+                new SimpleDateFormat("yyyy-MM-dd", Locale.ROOT).parse("2016-03-26"));
+        assertEquals("2016|M|", dateStr);
+    }
+}