mirror of https://github.com/apache/poi.git
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:
parent
2e74d762cf
commit
1a8a733cdf
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -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");
|
||||||
|
|
Loading…
Reference in New Issue