improved performance of DateUtil.isCellDateFormatted(), see Bugzilla 48425
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@893105 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
c89aeaee12
commit
3bbde4880c
@ -34,6 +34,7 @@
|
|||||||
|
|
||||||
<changes>
|
<changes>
|
||||||
<release version="3.7-SNAPSHOT" date="2010-??-??">
|
<release version="3.7-SNAPSHOT" date="2010-??-??">
|
||||||
|
<action dev="POI-DEVELOPERS" type="fix">48425 - improved performance of DateUtil.isCellDateFormatted() </action>
|
||||||
<action dev="POI-DEVELOPERS" type="fix">47215 - fixed InterfaceEndRecord to tolerate unexpected record contents </action>
|
<action dev="POI-DEVELOPERS" type="fix">47215 - fixed InterfaceEndRecord to tolerate unexpected record contents </action>
|
||||||
<action dev="POI-DEVELOPERS" type="fix">48415 - improved javadoc on HSSPicture.resize() </action>
|
<action dev="POI-DEVELOPERS" type="fix">48415 - improved javadoc on HSSPicture.resize() </action>
|
||||||
<action dev="POI-DEVELOPERS" type="add">added Ant target to install artifacts in local repository </action>
|
<action dev="POI-DEVELOPERS" type="add">added Ant target to install artifacts in local repository </action>
|
||||||
|
@ -47,6 +47,13 @@ public class DateUtil {
|
|||||||
|
|
||||||
private static final Pattern TIME_SEPARATOR_PATTERN = Pattern.compile(":");
|
private static final Pattern TIME_SEPARATOR_PATTERN = Pattern.compile(":");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The following patterns are used in {@link #isADateFormat(int, String)}
|
||||||
|
*/
|
||||||
|
private static final Pattern date_ptrn1 = Pattern.compile("^\\[\\$\\-.*?\\]");
|
||||||
|
private static final Pattern date_ptrn2 = Pattern.compile("^\\[[a-zA-Z]+\\]");
|
||||||
|
private static final Pattern date_ptrn3 = Pattern.compile("^[yYmMdDhHsS\\-/,. :\\\\]+[ampAMP/]*$");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given a Date, converts it into a double representing its internal Excel representation,
|
* Given a Date, converts it into a double representing its internal Excel representation,
|
||||||
* which is the number of days since 1/1/1900. Fractional days represent hours, minutes, and seconds.
|
* which is the number of days since 1/1/1900. Fractional days represent hours, minutes, and seconds.
|
||||||
@ -181,6 +188,7 @@ public class DateUtil {
|
|||||||
calendar.set(GregorianCalendar.MILLISECOND, millisecondsInDay);
|
calendar.set(GregorianCalendar.MILLISECOND, millisecondsInDay);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given a format ID and its format String, will check to see if the
|
* Given a format ID and its format String, will check to see if the
|
||||||
* format represents a date format or not.
|
* format represents a date format or not.
|
||||||
@ -206,36 +214,62 @@ public class DateUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
String fs = formatString;
|
String fs = formatString;
|
||||||
|
/*
|
||||||
|
Normalize the format string. The code below is equivalent
|
||||||
|
to the following consecutive regexp replacements:
|
||||||
|
|
||||||
// Translate \- into just -, before matching
|
// Translate \- into just -, before matching
|
||||||
fs = fs.replaceAll("\\\\-","-");
|
fs = fs.replaceAll("\\\\-","-");
|
||||||
// And \, into ,
|
// And \, into ,
|
||||||
fs = fs.replaceAll("\\\\,",",");
|
fs = fs.replaceAll("\\\\,",",");
|
||||||
// And \. into .
|
// And \. into .
|
||||||
fs = fs.replaceAll("\\\\.",".");
|
fs = fs.replaceAll("\\\\\\.",".");
|
||||||
// And '\ ' into ' '
|
// And '\ ' into ' '
|
||||||
fs = fs.replaceAll("\\\\ "," ");
|
fs = fs.replaceAll("\\\\ "," ");
|
||||||
|
|
||||||
// If it end in ;@, that's some crazy dd/mm vs mm/dd
|
// If it end in ;@, that's some crazy dd/mm vs mm/dd
|
||||||
// switching stuff, which we can ignore
|
// switching stuff, which we can ignore
|
||||||
fs = fs.replaceAll(";@", "");
|
fs = fs.replaceAll(";@", "");
|
||||||
|
|
||||||
|
The code above was reworked as suggested in bug 48425:
|
||||||
|
simple loop is more efficient than consecutive regexp replacements.
|
||||||
|
*/
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for(int i = 0; i < fs.length(); i++){
|
||||||
|
char c = fs.charAt(i);
|
||||||
|
if(i < fs.length() - 1){
|
||||||
|
char nc = fs.charAt(i + 1);
|
||||||
|
if(c == '\\'){
|
||||||
|
switch (nc){
|
||||||
|
case '-':
|
||||||
|
case ',':
|
||||||
|
case '.':
|
||||||
|
case ' ':
|
||||||
|
case '\\':
|
||||||
|
//skip current '\' and continue to the next char
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else if (c == ';' && nc == '@'){
|
||||||
|
i++;
|
||||||
|
//skip ";@" duplets
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sb.append(c);
|
||||||
|
}
|
||||||
|
fs = sb.toString();
|
||||||
|
|
||||||
// If it starts with [$-...], then could be a date, but
|
// If it starts with [$-...], then could be a date, but
|
||||||
// who knows what that starting bit is all about
|
// who knows what that starting bit is all about
|
||||||
fs = fs.replaceAll("^\\[\\$\\-.*?\\]", "");
|
fs = date_ptrn1.matcher(fs).replaceAll("");
|
||||||
|
|
||||||
// If it starts with something like [Black] or [Yellow],
|
// If it starts with something like [Black] or [Yellow],
|
||||||
// then it could be a date
|
// then it could be a date
|
||||||
fs = fs.replaceAll("^\\[[a-zA-Z]+\\]", "");
|
fs = date_ptrn2.matcher(fs).replaceAll("");
|
||||||
|
|
||||||
// Otherwise, check it's only made up, in any case, of:
|
// Otherwise, check it's only made up, in any case, of:
|
||||||
// y m d h s - / , . :
|
// y m d h s - \ / , . :
|
||||||
// optionally followed by AM/PM
|
// optionally followed by AM/PM
|
||||||
if(fs.matches("^[yYmMdDhHsS\\-/,. :]+[ampAMP/]*$")) {
|
return date_ptrn3.matcher(fs).matches();
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -26,6 +26,7 @@ import junit.framework.TestCase;
|
|||||||
|
|
||||||
import org.apache.poi.hssf.HSSFTestDataSamples;
|
import org.apache.poi.hssf.HSSFTestDataSamples;
|
||||||
import org.apache.poi.hssf.model.InternalWorkbook;
|
import org.apache.poi.hssf.model.InternalWorkbook;
|
||||||
|
import org.apache.poi.ss.usermodel.DateUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class TestHSSFDateUtil
|
* Class TestHSSFDateUtil
|
||||||
@ -239,6 +240,10 @@ public final class TestHSSFDateUtil extends TestCase {
|
|||||||
"DD-MM-YY", "DD-mm-YYYY",
|
"DD-MM-YY", "DD-mm-YYYY",
|
||||||
"dd\\-mm\\-yy", // Sometimes escaped
|
"dd\\-mm\\-yy", // Sometimes escaped
|
||||||
"dd.mm.yyyy", "dd\\.mm\\.yyyy",
|
"dd.mm.yyyy", "dd\\.mm\\.yyyy",
|
||||||
|
"dd\\ mm\\.yyyy AM", "dd\\ mm\\.yyyy pm",
|
||||||
|
"dd\\ mm\\.yyyy\\-dd", "[h]:mm:ss",
|
||||||
|
|
||||||
|
//YK: TODO "mm:ss.0" is a built-in date format which is not recognized by DateUtil.isInternalDateFormat
|
||||||
|
|
||||||
// These crazy ones are valid
|
// These crazy ones are valid
|
||||||
"yyyy-mm-dd;@", "yyyy/mm/dd;@",
|
"yyyy-mm-dd;@", "yyyy/mm/dd;@",
|
||||||
|
Loading…
Reference in New Issue
Block a user