1

I have stored my timestamps as Timestamp in my MySQL database. I retrieve them on my server, which works with UTC, and then convert these objects to json with Gson. Gson uses the JVM's timezone so it uses UTC on the server, which is what I want.

On my client side, I am in another timezone ("Europe/Amsterdam"), so I try to display dates in that timezone. I am retrieving the json, and then convert it to a list of objects using Gson. The dates that I retrieve at my client are UTC, so that is all going well. The objects have a Date attribute to store the dates. The json looks like this (partly):

{"id":2,"timestamp_start":"Jan 13, 2015 10:44:45 AM GMT",...}

In the conversion I used the following TypeAdapter:

public class DateTypeAdapter implements JsonSerializer<Date>, JsonDeserializer<Date> {

    private final DateFormat dateFormat;

    public DateTypeAdapter() {
        dateFormat = new SimpleDateFormat("MMM d, yyyy HH:mm:ss a", Locale.US);
        dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
    }

    @Override public synchronized JsonElement serialize(Date date, Type type,
        JsonSerializationContext jsonSerializationContext) {
        return new JsonPrimitive(dateFormat.format(date));
    }

    @Override public synchronized Date deserialize(JsonElement jsonElement, Type type,
        JsonDeserializationContext jsonDeserializationContext) {
      try {
        return dateFormat.parse(jsonElement.getAsString());
      } catch (ParseException e) {
        throw new JsonParseException(e);
      }
    }
}

Then, to show dates in e.g. Tableviews, I simply use this to convert from UTC:

public static String dateToLocalTimeString(Date date) {

    DateFormat formatter = new SimpleDateFormat("dd-MM-yyyy 'om' HH:mm");
    formatter.setTimeZone(TimeZone.getTimeZone("Europe/Amsterdam"));
    return formatter.format(date);

}

The problem is: it keeps showing the same date and time as is stored in the database, which is UTC. Even if I get rid of the TypeAdapter, it does.

What am I missing here?

After the conversion, I tested the Date by calling toString(), and it shows the same date and time but now "CEST" appended, which I do not understand. I should be +2, but it is just the same date and time...

UPDATE 2: I now tried the conversion like this (based on Java 8 Date API)

public static String dateToLocalTimeString(Date date) {

    LocalDateTime ldt = LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());

    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MM-yyyy 'om' HH:mm");
    String formattedDateTime = ldt.format(formatter);

    return formattedDateTime;
}

It stills shows the time 2 hours early. I have printed the epoch timestamp now, and it has just converted GMT -> CEST without converting the time. So I assume the above TypeAdapter is not working, so in my opinion it has something to do with Gson..

bashoogzaad
  • 4,611
  • 8
  • 40
  • 65
  • Would you be willing to hear a solution that uses [joda-time](http://www.joda.org/joda-time/), or do you want to keep responses to the base JDK? – durron597 Aug 14 '15 at 13:54
  • Due to the complexity of the system, shared classes on server and client, I would like to stick with storing the timestamp as `java.util.Date`. But this has to do with showing the date, so if this is possible with joda-time, I am ok with that.. – bashoogzaad Aug 14 '15 at 13:56
  • 1
    The problem is that the JDK, `java.util.Date`, `java.util.Calendar`, etc. is really bad at stuff like this; that's why libraries like joda time exist. I use joda time as a dependency in everything I do. – durron597 Aug 14 '15 at 13:57
  • 1
    Regardless, your problem is not gson, your problem is the JDK date libraries. In fact... – durron597 Aug 14 '15 at 14:00
  • possible duplicate of [Convert Date/Time for given Timezone - java](http://stackoverflow.com/questions/7670355/convert-date-time-for-given-timezone-java) – durron597 Aug 14 '15 at 14:00
  • see update 2 with my reasons for why I think it has something to do with `Gson` – bashoogzaad Aug 14 '15 at 14:28

3 Answers3

1

Try to have SimpleDateFormat as MMM d, yyyy HH:mm:ss a z

{"id":2,"timestamp_start":"Jan 13, 2015 10:44:45 AM GMT",...}

In the conversion I used the following TypeAdapter:

public class DateTypeAdapter implements JsonSerializer<Date>, JsonDeserializer<Date> {

    private final DateFormat dateFormat;

    public DateTypeAdapter() {
        dateFormat = new SimpleDateFormat("MMM d, yyyy HH:mm:ss a z", Locale.US);
        dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
    }

    @Override public synchronized JsonElement serialize(Date date, Type type,
        JsonSerializationContext jsonSerializationContext) {
        return new JsonPrimitive(dateFormat.format(date));
    }

    @Override public synchronized Date deserialize(JsonElement jsonElement, Type type,
        JsonDeserializationContext jsonDeserializationContext) {
      try {
        return dateFormat.parse(jsonElement.getAsString());
      } catch (ParseException e) {
        throw new JsonParseException(e);
      }
    }
}
Rafi
  • 833
  • 13
  • 17
M S Parmar
  • 955
  • 8
  • 22
0

Use this function to covert UTC (sourceTZ) to other timezone

public static String converDateTZ(String dateFormat, String dateString ,  String sourceTZ, String destiTZ) {

    DateFormat sourceFormat = new SimpleDateFormat("MMM d, yyyy HH:mm:ss a z");
    sourceFormat.setTimeZone(TimeZone.getTimeZone(sourceTZ));
    Date date = null;
    String parsDate = null;
    if (dateString != null) {
        try {
            date = sourceFormat.parse(dateString);
            DateFormat dFormat = new SimpleDateFormat(dateFormat);
            if (destiTZ != null) {
                dFormat.setTimeZone(TimeZone.getTimeZone(destiTZ));
            }
            parsDate = dFormat.format(date);
        } catch (ParseException e) {
            return "";
        }
        return parsDate;
    } else {
        return "";
    }

}

M S Parmar
  • 955
  • 8
  • 22
0

I have chosen to create a DateTypeAdapter, which does not use a SimpleDateFormat, because it looks like it does some unexpected things (which I do not know how to solve). I now convert all dates to epoch at the server, and convert them back at the client. Very easy, and does not use any timezone.

public class DateTypeAdapter implements JsonSerializer<Date>, JsonDeserializer<Date> {

    public DateTypeAdapter() {
    }

    @Override 
    public synchronized JsonElement serialize(Date date, Type type, JsonSerializationContext jsonSerializationContext) {
        return new JsonPrimitive(date.getTime());
    }

    @Override 
    public synchronized Date deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) {
        return new Date(Long.parseLong(jsonElement.getAsString()));
    }
}

When I want to show dates at the client, I can just show it with a SimpleDateFormat.

bashoogzaad
  • 4,611
  • 8
  • 40
  • 65