mirror of
https://github.com/apache/poi.git
synced 2026-02-27 20:40:08 +08:00
[bug-69681] allow 1 optional space in date formats before the AM/PM part
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1926508 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
779358f309
commit
c784266438
@ -70,7 +70,7 @@ public class DateUtil {
|
||||
private static final Pattern date_ptrn2 = Pattern.compile("^\\[[a-zA-Z]+]");
|
||||
private static final Pattern date_ptrn3a = Pattern.compile("[yYmMdDhHsS]");
|
||||
// add "\u5e74 \u6708 \u65e5" for Chinese/Japanese date format:2017 \u5e74 2 \u6708 7 \u65e5
|
||||
private static final Pattern date_ptrn3b = Pattern.compile("^[\\[\\]yYmMdDhHsS\\-T/\u5e74\u6708\u65e5,. :\"\\\\]+0*[ampAMP/]*$");
|
||||
private static final Pattern date_ptrn3b = Pattern.compile("^[\\[\\]yYmMdDhHsS\\-T/\u5e74\u6708\u65e5,. :\"\\\\]+0* ?[ampAMP/]*$");
|
||||
// elapsed time patterns: [h],[m] and [s]
|
||||
private static final Pattern date_ptrn4 = Pattern.compile("^\\[([hH]+|[mM]+|[sS]+)]");
|
||||
|
||||
@ -548,6 +548,7 @@ public class DateUtil {
|
||||
// avoid re-checking DateUtil.isADateFormat(int, String) if a given format
|
||||
// string represents a date format if the same string is passed multiple times.
|
||||
// see https://issues.apache.org/bugzilla/show_bug.cgi?id=55611
|
||||
private static boolean maintainCache = true;
|
||||
private static final ThreadLocal<Integer> lastFormatIndex = ThreadLocal.withInitial(() -> -1);
|
||||
private static final ThreadLocal<String> lastFormatString = new ThreadLocal<>();
|
||||
private static final ThreadLocal<Boolean> lastCachedResult = new ThreadLocal<>();
|
||||
@ -561,22 +562,24 @@ public class DateUtil {
|
||||
}
|
||||
|
||||
private static boolean isCached(String formatString, int formatIndex) {
|
||||
return formatIndex == lastFormatIndex.get()
|
||||
return maintainCache && formatIndex == lastFormatIndex.get()
|
||||
&& formatString.equals(lastFormatString.get());
|
||||
}
|
||||
|
||||
private static void cache(String formatString, int formatIndex, boolean cached) {
|
||||
if (formatString == null || "".equals(formatString)) {
|
||||
lastFormatString.remove();
|
||||
} else {
|
||||
lastFormatString.set(formatString);
|
||||
if (maintainCache) {
|
||||
if (formatString == null || "".equals(formatString)) {
|
||||
lastFormatString.remove();
|
||||
} else {
|
||||
lastFormatString.set(formatString);
|
||||
}
|
||||
if (formatIndex == -1) {
|
||||
lastFormatIndex.remove();
|
||||
} else {
|
||||
lastFormatIndex.set(formatIndex);
|
||||
}
|
||||
lastCachedResult.set(cached);
|
||||
}
|
||||
if (formatIndex == -1) {
|
||||
lastFormatIndex.remove();
|
||||
} else {
|
||||
lastFormatIndex.set(formatIndex);
|
||||
}
|
||||
lastCachedResult.set(cached);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -997,4 +1000,18 @@ public class DateUtil {
|
||||
|
||||
return tm;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable or disable the thread-local cache for date format checking.
|
||||
* If enabled, the date format checking will be cached per thread,
|
||||
* which can improve performance when checking the same format multiple times.
|
||||
* If disabled, the cache will not be used and each check will be performed independently.
|
||||
*
|
||||
* @param enable true to enable the cache, false to disable it (enabled, by default)
|
||||
* @since POI 5.4.2
|
||||
*/
|
||||
public static void enableThreadLocalCache(final boolean enable) {
|
||||
// enable thread-local cache for date format checking
|
||||
maintainCache = enable;
|
||||
}
|
||||
}
|
||||
|
||||
@ -27,6 +27,7 @@ import java.util.TimeZone;
|
||||
|
||||
import org.apache.poi.hssf.HSSFTestDataSamples;
|
||||
import org.apache.poi.hssf.model.InternalWorkbook;
|
||||
import org.apache.poi.ss.usermodel.DataFormatter;
|
||||
import org.apache.poi.ss.usermodel.DateUtil;
|
||||
import org.apache.poi.util.LocaleUtil;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
@ -60,7 +61,7 @@ class TestHSSFDateUtil {
|
||||
|
||||
HSSFWorkbook workbook = HSSFTestDataSamples.openSampleWorkbook("DateFormats.xls");
|
||||
HSSFSheet sheet = workbook.getSheetAt(0);
|
||||
InternalWorkbook wb = workbook.getWorkbook();
|
||||
InternalWorkbook wb = workbook.getWorkbook();
|
||||
assertNotNull(wb);
|
||||
|
||||
HSSFRow row;
|
||||
@ -115,4 +116,27 @@ class TestHSSFDateUtil {
|
||||
|
||||
workbook.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testIsADateFormat() throws IOException {
|
||||
try (HSSFWorkbook workbook = new HSSFWorkbook()) {
|
||||
HSSFSheet sheet = workbook.createSheet();
|
||||
HSSFRow row = sheet.createRow(0);
|
||||
HSSFCell cell = row.createCell(0);
|
||||
cell.setCellValue(45825.5); // 2025-06-17 (midday)
|
||||
HSSFCellStyle style = workbook.createCellStyle();
|
||||
style.setDataFormat(workbook.createDataFormat().getFormat("DD MMMM, YYYY hh:mm:ss.000 AM/PM"));
|
||||
cell.setCellStyle(style);
|
||||
DateUtil.enableThreadLocalCache(false);
|
||||
try {
|
||||
assertTrue(DateUtil.isCellDateFormatted(cell), "cell is date formatted?");
|
||||
DataFormatter formatter = new DataFormatter();
|
||||
String formattedValue = formatter.formatCellValue(cell);
|
||||
assertEquals("17 June, 2025 12:00:00.000 PM", formattedValue);
|
||||
} finally {
|
||||
DateUtil.enableThreadLocalCache(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user