Bug 60369: Adjust pattern to better handle non-ASCII characters in Month-names which can appear since Java 8

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1776646 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Dominik Stadler 2016-12-30 22:11:55 +00:00
parent da2b7c0969
commit 6f616d0a51
2 changed files with 168 additions and 8 deletions

View 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"
);
}

View File

@ -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);
}
}