I am parsing JSON from server in my Android application by using Jackson JSON library. However, parsing requests fail whenever I receive DateTime since it's in this format:
"/Date(1277931782420)/"
I know I should do something like:
ObjectMapper om = new ObjectMapper();
om.setDateFormat(new TicksSinceFormat());
But I have no idea if I can use SimpleDateFormat at all (and what format string would I use?) or I need to write my own DateFormat parser. So, I would seriously appreciate if somebody could help with code example.
EDIT: OK, see my answer for complete code.
This proved to be tougher then I expected:
public class TicksSinceFormat extends DateFormat {
@Override
public StringBuffer format(Date date, StringBuffer buffer, FieldPosition field) {
long millis = date.getTime();
return new StringBuffer("/Date(" + millis + ")/");
}
@Override
public Date parse(String string, ParsePosition position) {
int start = string.indexOf("(") + 1;
int end = string.indexOf(")");
String ms = string.substring(start, end);
Date date = new Date(Long.parseLong(ms));
position.setIndex(string.length() - 1); // MUST SET THIS
return date;
}
@Override
public Object clone() {
return new TicksSinceFormat(); // MUST SET THIS
}
}
Using class is then extremely simple, just do:
ObjectMapper om = new ObjectMapper();
om.setDateFormat(new TicksSinceFormat())
I presume that this can be coded better + that I'll need to deal with differences when it comes to .NET Ticks VS Java ticks - but for now this'll do. If somebody has better solution or more insight into mentioned problems I'll deal with later - feel free to post and I'll mark your answer as correct one if it's better.
EDIT: As I've explained in this question & answer I've switched to ServiceStack.Text library on the server and it returns different, ISO8601 format. For that format I'm using slightly different parsing (since Jackson has trouble parsing ISO8601 that contains milliseconds). Of course, as with other code I'm posting - let me know if you have better version (just please post code / edit this post, rather than resorting to philosophical rhetoric on how it should be done):
@SuppressLint("SimpleDateFormat")
public class JacksonSimpleDateFormat extends SimpleDateFormat {
public JacksonSimpleDateFormat() {
if (mParser == null) {
mParser = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
mParser.setTimeZone(TimeZone.getTimeZone("UTC"));
}
}
@Override
public StringBuffer format(Date date, StringBuffer buffer, FieldPosition field) {
return mParser.format(date, buffer, field);
}
private static SimpleDateFormat mParser;
@Override
public Date parse(String string, ParsePosition position) {
String str = string.split("\\.")[0];
Date date = null;
try {
date = mParser.parse(str);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
position.setIndex(string.length() - 1);
return date;
}
@Override
public Object clone() {
return new JacksonSimpleDateFormat();
}
}
I may be wrong on this, as I haven't gotten very far into Android development, but the format you presented:
"/Date(1277931782420)/"
Appears to be Unix epoch time.
If that is the case, you would not want/need to use SimpleDateFormat
. Instead, try creating a Long
from it and passing to the Date
constructor, accounting for whether it is seconds or milliseconds-based epoch value.
Here is a StackOverflow post that provides the code for doing so: https://stackoverflow.com/a/535017/463196
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With