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:
parent
da2b7c0969
commit
6f616d0a51
@ -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"
|
||||
);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user