使用Gson将时间从UTC转换为其他时区失败

时间:2015-08-14 12:20:55

标签: java json datetime timezone gson

我已将时间戳存储为Timestamp在MySQL数据库中。我在我的服务器上检索它们,它使用UTC,然后使用Gson将这些对象转换为json。 Gson使用JVM的时区,因此它在服务器上使用UTC,这就是我想要的。

在我的客户端,我在另一个时区("欧洲/阿姆斯特丹"),所以我尝试在该时区显示日期。我正在检索json,然后使用Gson将其转换为对象列表。我在客户端检索的日期是UTC,所以一切顺利。对象具有Date属性来存储日期。 json看起来像这样(部分):

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

在转换过程中,我使用了以下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);
      }
    }
}

然后,在例如显示日期Tableviews,我只是用它来转换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);

}

问题是:它始终显示与数据库中存储的日期和时间相同的日期和时间,即UTC。即使我摆脱TypeAdapter,它也会。

我在这里缺少什么?

转换后,我通过调用Date测试了toString(),它显示了相同的日期和时间,但现在&#34; CEST&#34;附上,我不明白。我应该是+2,但它只是相同的日期和时间......

更新2:我现在尝试了这样的转换(基于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;
}

它仍然显示提前2小时的时间。我现在已经打印了纪元时间戳,它刚刚转换为GMT - &gt; CEST没有转换时间。所以我认为上面的TypeAdapter无效,所以在我看来它与Gson有关..

2 个答案:

答案 0 :(得分:1)

尝试将SimpleDateFormat设为 MMM d,yyyy HH:mm:ss a z

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

在转换过程中,我使用了以下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);
      }
    }
}

答案 1 :(得分:0)

我选择创建一个DateTypeAdapter,它不使用SimpleDateFormat,因为它看起来像是一些意想不到的事情(我不知道如何解决)。我现在将所有日期转换为服务器上的纪元,并在客户端将其转换回来。非常简单,不使用任何时区。

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()));
    }
}

当我想在客户端显示日期时,我可以使用SimpleDateFormat显示日期。