From 6721eeaf2367bc852446ba9b431a8464daa56ad1 Mon Sep 17 00:00:00 2001 From: Peter Wu Date: Sat, 10 May 2014 18:29:17 +0200 Subject: Convert String to DateTime (for created_at) Extra efforts are done to keep the timezone information. --- lib/joda-time-2.3.jar | Bin 0 -> 581571 bytes nbproject/project.properties | 4 ++- src/data/Tweet.java | 3 +- src/data/TwitterJsonDeserializer.java | 5 ++- src/data/User.java | 4 ++- src/database/NamedPreparedStatement.java | 12 ++++++++ src/database/QueryUtils.java | 4 +-- src/utils/TwitterDateAdapter.java | 51 +++++++++++++++++++++++++++++++ 8 files changed, 77 insertions(+), 6 deletions(-) create mode 100644 lib/joda-time-2.3.jar create mode 100644 src/utils/TwitterDateAdapter.java diff --git a/lib/joda-time-2.3.jar b/lib/joda-time-2.3.jar new file mode 100644 index 0000000..9dce4f9 Binary files /dev/null and b/lib/joda-time-2.3.jar differ diff --git a/nbproject/project.properties b/nbproject/project.properties index f6acd32..41b3c73 100644 --- a/nbproject/project.properties +++ b/nbproject/project.properties @@ -31,13 +31,15 @@ endorsed.classpath= excludes= file.reference.commons-lang3-3.3.2.jar=lib/commons-lang3-3.3.2.jar file.reference.gson-2.2.4.jar=lib/gson-2.2.4.jar +file.reference.joda-time-2.3.jar=lib/joda-time-2.3.jar file.reference.postgresql-9.3-1101.jdbc41.jar=lib/postgresql-9.3-1101.jdbc41.jar includes=** jar.compress=false javac.classpath=\ ${file.reference.postgresql-9.3-1101.jdbc41.jar}:\ ${file.reference.gson-2.2.4.jar}:\ - ${file.reference.commons-lang3-3.3.2.jar} + ${file.reference.commons-lang3-3.3.2.jar}:\ + ${file.reference.joda-time-2.3.jar} # Space-separated list of extra javac options javac.compilerargs= javac.deprecation=false diff --git a/src/data/Tweet.java b/src/data/Tweet.java index 04b5f2c..320adbb 100644 --- a/src/data/Tweet.java +++ b/src/data/Tweet.java @@ -1,5 +1,6 @@ package data; +import org.joda.time.DateTime; /** * Represents the tweet object as returned by the twitter API. @@ -10,7 +11,7 @@ public class Tweet { public String lang; @ValidatingJsonDeserializer.Nullable public long in_reply_to_user_id; - public String created_at; + public DateTime created_at; public long favorite_count; @ValidatingJsonDeserializer.Nullable @ValidatingJsonDeserializer.Validator diff --git a/src/data/TwitterJsonDeserializer.java b/src/data/TwitterJsonDeserializer.java index 47506d0..29ff87d 100644 --- a/src/data/TwitterJsonDeserializer.java +++ b/src/data/TwitterJsonDeserializer.java @@ -1,6 +1,8 @@ package data; +import utils.TwitterDateAdapter; import com.google.gson.GsonBuilder; +import org.joda.time.DateTime; /** * Deserializer for Twitter objects. @@ -15,7 +17,8 @@ public class TwitterJsonDeserializer extends ValidatingJsonDeserializer { } private static GsonBuilder getBaseGsonBuilder() { - return new GsonBuilder(); + return new GsonBuilder() + .registerTypeAdapter(DateTime.class, new TwitterDateAdapter()); } public static GsonBuilder getGsonBuilder() { diff --git a/src/data/User.java b/src/data/User.java index 91b5e07..61de759 100644 --- a/src/data/User.java +++ b/src/data/User.java @@ -1,5 +1,7 @@ package data; +import org.joda.time.DateTime; + /** * Represents the user object from the Twitter API as contained in a tweet. */ @@ -14,7 +16,7 @@ public class User { public long friends_count; public String location; public String screen_name; - public String created_at; + public DateTime created_at; @ValidatingJsonDeserializer.Nullable @ValidatingJsonDeserializer.Validator public Entities entities; diff --git a/src/database/NamedPreparedStatement.java b/src/database/NamedPreparedStatement.java index f635891..398ef60 100644 --- a/src/database/NamedPreparedStatement.java +++ b/src/database/NamedPreparedStatement.java @@ -3,10 +3,14 @@ package database; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; +import java.sql.Timestamp; import java.util.ArrayList; +import java.util.Calendar; import java.util.List; +import java.util.Locale; import java.util.regex.Matcher; import java.util.regex.Pattern; +import org.joda.time.DateTime; /** * Allows a prepared statement to contain named parameters instead of a question @@ -64,6 +68,14 @@ public class NamedPreparedStatement { } } + public void setTimestamp(String name, DateTime dt) throws SQLException { + for (int paramIndex : getParamIndices(name)) { + Timestamp tsp = new Timestamp(dt.getMillis()); + Calendar calendar = dt.toCalendar(Locale.ENGLISH); + stmt.setTimestamp(paramIndex, tsp, calendar); + } + } + public PreparedStatement getStmt() { return stmt; } diff --git a/src/database/QueryUtils.java b/src/database/QueryUtils.java index 0957647..ff26ec4 100644 --- a/src/database/QueryUtils.java +++ b/src/database/QueryUtils.java @@ -91,7 +91,7 @@ public class QueryUtils { NamedPreparedStatement profileStatement, Tweet tweet) throws SQLException { tweetStatement.setLong("tweetid", tweet.id); - tweetStatement.setString("createdat", tweet.created_at); + tweetStatement.setTimestamp("createdat", tweet.created_at); tweetStatement.setLong("favcount", tweet.favorite_count); tweetStatement.setLong("retweetcount", tweet.retweet_count); tweetStatement.setString("text", tweet.text); @@ -126,7 +126,7 @@ public class QueryUtils { profileStatement.setLong("followedcount", twuser.friends_count); profileStatement.setString("location", twuser.location); profileStatement.setString("tweetname", twuser.screen_name); - profileStatement.setString("createdat", twuser.created_at); + profileStatement.setTimestamp("createdat", twuser.created_at); profileStatement.setString("language", twuser.lang); } diff --git a/src/utils/TwitterDateAdapter.java b/src/utils/TwitterDateAdapter.java new file mode 100644 index 0000000..b3c8f37 --- /dev/null +++ b/src/utils/TwitterDateAdapter.java @@ -0,0 +1,51 @@ +package utils; + +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonParseException; +import com.google.gson.JsonPrimitive; +import com.google.gson.JsonSerializationContext; +import com.google.gson.JsonSerializer; +import java.lang.reflect.Type; +import org.joda.time.DateTime; +import org.joda.time.format.DateTimeFormat; +import org.joda.time.format.DateTimeFormatter; + +/** + * Converts a Twitter date string to a DateTime with timezone. + * + * @author Peter Wu + */ +public class TwitterDateAdapter implements JsonDeserializer, + JsonSerializer { + + private static final DateTimeFormatter DATE_FORMATTER + = DateTimeFormat.forPattern("EEE MMM dd HH:mm:ss Z yyyy") + .withOffsetParsed(); + + @Override + public DateTime deserialize(JsonElement je, Type type, + JsonDeserializationContext jdc) throws JsonParseException { + JsonPrimitive jp; + if (!je.isJsonPrimitive() || !(jp = je.getAsJsonPrimitive()).isString()) { + throw new JsonParseException("Invalid date type"); + } + String datetime = jp.getAsString(); + try { + return DATE_FORMATTER.parseDateTime(datetime); + } catch (IllegalArgumentException ex) { + throw new JsonParseException("Invalid date: " + datetime, ex); + } + } + + @Override + public JsonElement serialize(DateTime t, Type type, + JsonSerializationContext jsc) { + return new JsonPrimitive(formatDateTime(t)); + } + + public static String formatDateTime(DateTime t) { + return DATE_FORMATTER.print(t); + } +} -- cgit v1.2.1