59183 - handle timezones (even with colons) in date parsing metadata in ooxml opc

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1735270 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Tim Allison 2016-03-16 17:52:42 +00:00
parent 2e74d762cf
commit 1a8a733cdf
2 changed files with 79 additions and 16 deletions

View File

@ -23,6 +23,8 @@ import java.text.ParsePosition;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Date; import java.util.Date;
import java.util.Locale; import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException; import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.exceptions.InvalidOperationException; import org.apache.poi.openxml4j.exceptions.InvalidOperationException;
@ -49,9 +51,22 @@ public final class PackagePropertiesPart extends PackagePart implements
public final static String NAMESPACE_DCTERMS_URI = "http://purl.org/dc/terms/"; public final static String NAMESPACE_DCTERMS_URI = "http://purl.org/dc/terms/";
private final static String DEFAULT_DATEFORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'"; private final static String DEFAULT_DATEFORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'";
private final static String ALTERNATIVE_DATEFORMAT = "yyyy-MM-dd'T'HH:mm:ss.SS'Z'";
private final static String[] DATE_FORMATS = new String[]{
DEFAULT_DATEFORMAT,
"yyyy-MM-dd'T'HH:mm:ss.SS'Z'",
};
//Had to add this and TIME_ZONE_PAT to handle tz with colons.
//When we move to Java 7, we should be able to add another
//date format to DATE_FORMATS that uses XXX and get rid of this
//and TIME_ZONE_PAT
private final String[] TZ_DATE_FORMATS = new String[]{
"yyyy-MM-dd'T'HH:mm:ssz",
"yyyy-MM-dd'T'HH:mm:ss.SSSz"
};
private final Pattern TIME_ZONE_PAT = Pattern.compile("([-+]\\d\\d):?(\\d\\d)");
/** /**
* Constructor. * Constructor.
* *
@ -562,20 +577,43 @@ public final class PackagePropertiesPart extends PackagePart implements
if (dateStr == null || dateStr.equals("")) { if (dateStr == null || dateStr.equals("")) {
return new Nullable<Date>(); return new Nullable<Date>();
} }
Matcher m = TIME_ZONE_PAT.matcher(dateStr);
if (m.find()) {
String dateTzStr = dateStr.substring(0, m.start())+
m.group(1)+m.group(2);
for (String fStr : TZ_DATE_FORMATS) {
SimpleDateFormat df = new SimpleDateFormat(fStr, Locale.ROOT);
df.setTimeZone(LocaleUtil.TIMEZONE_UTC);
Date d = new SimpleDateFormat(fStr).parse(dateTzStr, new ParsePosition(0));
if (d != null) {
return new Nullable<Date>(d);
}
}
}
String dateTzStr = dateStr.endsWith("Z") ? dateStr : (dateStr + "Z"); String dateTzStr = dateStr.endsWith("Z") ? dateStr : (dateStr + "Z");
SimpleDateFormat df = new SimpleDateFormat(DEFAULT_DATEFORMAT, Locale.ROOT); for (String fStr : DATE_FORMATS) {
df.setTimeZone(LocaleUtil.TIMEZONE_UTC); SimpleDateFormat df = new SimpleDateFormat(fStr, Locale.ROOT);
Date d = df.parse(dateTzStr, new ParsePosition(0)); df.setTimeZone(LocaleUtil.TIMEZONE_UTC);
if (d == null) { Date d = df.parse(dateTzStr, new ParsePosition(0));
df = new SimpleDateFormat(ALTERNATIVE_DATEFORMAT, Locale.ROOT); if (d != null) {
df.setTimeZone(LocaleUtil.TIMEZONE_UTC); return new Nullable<Date>(d);
d = df.parse(dateTzStr, new ParsePosition(0)); }
} }
if (d == null) { //if you're here, no pattern matched, throw exception
throw new InvalidFormatException("Date " + dateTzStr + " not well formated, " StringBuilder sb = new StringBuilder();
+ "expected format " + DEFAULT_DATEFORMAT + " or " + ALTERNATIVE_DATEFORMAT); int i = 0;
for (String fStr : TZ_DATE_FORMATS) {
if (i++ > 0) {
sb.append(", ");
}
sb.append(fStr);
} }
return new Nullable<Date>(d); for (String fStr : DATE_FORMATS) {
sb.append(", ").append(fStr);
}
throw new InvalidFormatException("Date " + dateStr + " not well formatted, "
+ "expected format in: "+sb.toString());
} }
/** /**

View File

@ -70,11 +70,36 @@ public final class TestPackageCoreProperties {
df.setTimeZone(LocaleUtil.TIMEZONE_UTC); df.setTimeZone(LocaleUtil.TIMEZONE_UTC);
Date dateToInsert = df.parse("2007-05-12T08:00:00Z", new ParsePosition(0)); Date dateToInsert = df.parse("2007-05-12T08:00:00Z", new ParsePosition(0));
SimpleDateFormat msdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.ROOT);
msdf.setTimeZone(LocaleUtil.TIMEZONE_UTC);
PackageProperties props = p.getPackageProperties(); PackageProperties props = p.getPackageProperties();
props.setCategoryProperty("MyCategory");
//test various date formats
props.setCreatedProperty("2007-05-12T08:00:00Z");
assertEquals(dateToInsert, props.getCreatedProperty().getValue());
props.setCreatedProperty("2007-05-12T08:00:00"); //no Z, assume Z
assertEquals(dateToInsert, props.getCreatedProperty().getValue());
props.setCreatedProperty("2007-05-12T08:00:00.123Z");//millis
assertEquals(msdf.parse("2007-05-12T08:00:00.123Z"), props.getCreatedProperty().getValue());
props.setCreatedProperty("2007-05-12T10:00:00+0200");
assertEquals(dateToInsert, props.getCreatedProperty().getValue());
props.setCreatedProperty("2007-05-12T10:00:00+02:00");//colon in tz
assertEquals(dateToInsert, props.getCreatedProperty().getValue());
props.setCreatedProperty("2007-05-12T06:00:00-0200");
assertEquals(dateToInsert, props.getCreatedProperty().getValue());
props.setCreatedProperty("2007-05-12T10:00:00.123+0200");
assertEquals(msdf.parse("2007-05-12T08:00:00.123Z"), props.getCreatedProperty().getValue());
props.setCategoryProperty("MyCategory");
props.setContentStatusProperty("MyContentStatus"); props.setContentStatusProperty("MyContentStatus");
props.setContentTypeProperty("MyContentType"); props.setContentTypeProperty("MyContentType");
props.setCreatedProperty(new Nullable<Date>(dateToInsert));
props.setCreatorProperty("MyCreator"); props.setCreatorProperty("MyCreator");
props.setDescriptionProperty("MyDescription"); props.setDescriptionProperty("MyDescription");
props.setIdentifierProperty("MyIdentifier"); props.setIdentifierProperty("MyIdentifier");