How to fix inaccurate DateTime (minutes) parsed by Jackson / Gson libraries?

I am developing an Android application that interacts with some of the Google App Engine web services.

This application implements the chat function, which has a very simple function: send text .

During debugging, I noticed that the messages that I posted from the server did not appear in the same order that I sent in my application. At first I thought the problem was with the server.

First I checked the raw Json that I was getting:

{ "messages": [ { "message": "test 3", "author": "daniel", "message_id": "5724160613416960", "sent_at": "2014-11-13T09:42:42.861950" }, { "message": "test 2", "author": "daniel", "message_id": "5649050225344512", "sent_at": "2014-11-13T09:42:10.390960" }, { "message": "test 1", "author": "daniel", "message_id": "5178081291534336", "sent_at": "2014-11-13T09:41:01.998830" } ], "kind": "company#chatsItem", "etag": "\"RUCkC9XynEQNZ2t5E0aa41edXro/xRNtgkWIUbq4zCgmv2iq2fy-UIg\"" } 

As you can see, the raw data is properly ordered. But here comes the funny part. When I add a JSON parser such as JacksonFactory (or even GsonFactory):

 Company.Builder builder = new Company.Builder(AndroidHttp.newCompatibleTransport(), new JacksonFactory(), null); Company service = builder.build(); ChatsChatCollectionResponse response = service.chats().list(user_id, album_id, token).execute(); List<ChatsChatResponse> messagesResponse = response.getMessages(); 

Here the ChatsChatResponse elements are ordered in the same way as above:

 [0] = { com.appspot.com_pany.company.model.ChatsChatResponse@83002906309 6} size = 4 [0] = { com.google.api.client.util.DataMap$Entry@830029082528 }"author" -> "daniel" [1] = { com.google.api.client.util.DataMap$Entry@830029082552 }"message" -> "test 3" [2] = { com.google.api.client.util.DataMap$Entry@830029082576 }"message_id" -> "5724160613416960" [3] = { com.google.api.client.util.DataMap$Entry@830029082600 }"sent_at" -> "2014-11-13T10:57:03.950+01:00" [1] = { com.appspot.com_pany.company.model.ChatsChatResponse@83002906637 6} size = 4 [0] = { com.google.api.client.util.DataMap$Entry@830029083616 }"author" -> "daniel" [1] = {c om.google.api.client.util.DataMap$Entry@830029083640 }"message" -> "test 2" [2] = { com.google.api.client.util.DataMap$Entry@830029083664 }"message_id" -> "5649050225344512" [3] = { com.google.api.client.util.DataMap$Entry@830029083688 }"sent_at" -> "2014-11-13T10:48:40.960+01:00" [2] = { com.appspot.com_pany.company.model.ChatsChatResponse@83002906800 8} size = 4 [0] = { com.google.api.client.util.DataMap$Entry@830029084760 }"author" -> "daniel" [1] = { com.google.api.client.util.DataMap$Entry@830029084784 }"message" -> "test 1" [2] = { com.google.api.client.util.DataMap$Entry@830029084808 }"message_id" -> "5178081291534336" [3] = { com.google.api.client.util.DataMap$Entry@830029084832 }"sent_at" -> "2014-11-13T10:57:39.830+01:00" 

Why is there such a random difference in the sent_at field?

EDIT I forgot to mention that I'm not talking about a 1-hour shift that corresponds to TimeZone, but rather how random the minutes are.

+5
source share
3 answers

I'm not sure about the solution, but the explanation seems perfectly clear: the variation is not random at all, but rather caused by the addition of everything after the decimal point in milliseconds.

Take the third entry, for example:

 2014-11-13T09:41:01.998830 

Obviously, the parser reads this as:

 hours: 09 minutes: 41 seconds: 01 milliseconds: 998830 

Since milliseconds are more than 1000, it is converted to 998s 830ms , which, when taking into account the full minutes of 16m 38s 830ms . Consequently:

 hours: 09 minutes: 41 + 16 seconds: 01 + 38 milliseconds: 830 

Which gives exactly the result that you see (modulo setting the time zone):

 2014-11-13T10:57:39.830+01:00 

If you have control over the exit of the service (this question is not entirely clear from the wording of the question), the simplest solution is to output only three digits after decimal points (i.e. rounding in milliseconds instead of millionths). For example, this will be 2014-11-13T09:41:01.999 .

You can also fix this on the parser itself, but this will require a little more research (and, ideally, the essence that reproduces the problem).

+3
source

try setting a custom date format like

Gson gson = new GsonBuilder () setDateFormat ("YYYY-MM-dd'T'HH: mm: SS.sss") .. Create ();

+1
source

As @matiash pointed out, you have a custom date format containing microseconds. The problem is that the SimpleDateFormat used by Jackson SimpleDateFormat not properly parse the microseconds .

To facilitate this, you should create your own deserializer that truncates microseconds to milliseconds:

 public class MicrosecondDateSerializer extends JsonDeserializer<Date> { private static SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyyThh:mm:ss:SSS"); @Override public Date deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { ObjectCodec oc = jp.getCodec(); JsonNode node = jp.getCodec().readTree(jp); String dateString = node.get("sent_at").asText(); String dateStringTruncated = dateString.substring(0, dateString.length() - 3); return formatter.parse(dateStringTruncated); } } 
0
source

Source: https://habr.com/ru/post/1206800/


All Articles