I\'m reading in date strings that could be with or without a time zone adjustment: yyyyMMddHHmmssz or yyyyMMddHHmmss. When a string is missing a z
I have solved a similar problem some time ago by extending SimpleDateFormat. Below an crude implementation to show the idea of my solution. It may not be fully complete/optimised.
public class MySimpleDateFormat extends SimpleDateFormat {
private static final long serialVersionUID = 1L;
private static String FORMAT = "
private static int FORMAT_LEN = "yyyyMMddHHmmss".length();
private static String TZ_ID = "GMT";
public MySimpleDateFormat() {
this(TimeZone.getTimeZone(TZ_ID));
}
public MySimpleDateFormat(TimeZone tz) {
super(FORMAT);
setTimeZone(tz);
}
@Override
public Date parse(String source, ParsePosition pos) {
// TODO: args validation
int offset = pos.getIndex() + FORMAT_LEN;
Date result;
if (offset < source.length()) {
// there maybe is a timezone
result = super.parse(source, pos);
if (result != null) {
return result;
}
if (pos.getErrorIndex() >= offset) {
// there isn't a TZ after all
String part0 = source.substring(0, offset);
String part1 = source.substring(offset);
ParsePosition anotherPos = new ParsePosition(pos.getIndex());
result = super.parse(part0 + TZ_ID + part1, anotherPos);
if(result == null) {
pos.setErrorIndex(anotherPos.getErrorIndex());
} else {
// check SimpleDateFormat#parse javadoc to implement correctly the pos updates
pos.setErrorIndex(-1);
pos.setIndex(offset);
}
return result;
}
// there's something wrong with the first FORMAT_LEN chars
return null;
}
result = super.parse(source + TZ_ID, pos);
if(result != null) {
pos.setIndex(pos.getIndex() - TZ_ID.length());
}
return result;
}
public static void main(String [] args) {
ParsePosition pos = new ParsePosition(0);
MySimpleDateFormat mySdf = new MySimpleDateFormat();
System.out.println(mySdf.parse("20120622131415", pos) + " -- " + pos);
pos = new ParsePosition(0);
System.out.println(mySdf.parse("20120622131415GMT", pos) + " -- " + pos);
pos = new ParsePosition(0);
System.out.println(mySdf.parse("20120622131415xxx", pos) + " -- " + pos);
pos = new ParsePosition(0);
System.out.println(mySdf.parse("20120x22131415xxx", pos) + " -- " + pos);
}
}
The gist is that you need to check the input string and "guess" somehow that the TZ field is missing, add it if so and then let the SimpleDateFormat#parse(String, ParsePosition) do the rest. The implementation above isn't updating ParsePosition according to the contract in javadoc in SimpleDateFormat#parse(String, ParsePosition)
The class has a single default ctor as there's only one format allowed.
The method MySimpleDateFormat#parse(String, ParsePosition) is invoked by SimpleDateFormat#parse(String) so it's sufficient to cover both cases.
Running the main() this is the output (as expected)
Fri Jun 22 14:14:15 BST 2012 -- java.text.ParsePosition[index=14,errorIndex=-1]
Fri Jun 22 14:14:15 BST 2012 -- java.text.ParsePosition[index=17,errorIndex=-1]
Fri Jun 22 14:14:15 BST 2012 -- java.text.ParsePosition[index=14,errorIndex=-1]
null -- java.text.ParsePosition[index=0,errorIndex=5]