【问题标题】:Convert TimeZone of Date in RequestBody of retrofit在改造的RequestBody中转换日期的时区
【发布时间】:2020-03-25 03:58:10
【问题描述】:

我正在使用改造来调用服务器,我有这样的 requestBody:

class MyRequestBody {
String id;
Date date;
}

我想在 requestBody 中转换日期对象的时区。

我试过这些东西:

Gson gson = new GsonBuilder()
.setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS zzz")
.create();

Retrofit.Builder adapterBuilder = new Retrofit
.Builder()
.baseUrl(baseUrl)
.addConverterFactory(GsonCustomConverterFactory.create(gson))

class GsonCustomConverterFactory extends Converter.Factory
{
    public static GsonCustomConverterFactory create(Gson gson) {
        return new GsonCustomConverterFactory(gson);
    }

    private final Gson gson;
    private final GsonConverterFactory gsonConverterFactory;

    private GsonCustomConverterFactory(Gson gson) {
        if (gson == null) throw new NullPointerException("gson == null");
        this.gson = gson;
        this.gsonConverterFactory = GsonConverterFactory.create(gson);
    }

    @Override
    public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
        if(type.equals(String.class))
            return new GsonResponseBodyConverterToString<Object>(gson, type);
        else
            return gsonConverterFactory.responseBodyConverter(type, annotations, retrofit);
    }

    @Override
    public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
        return gsonConverterFactory.requestBodyConverter(type, parameterAnnotations, methodAnnotations, retrofit);
    }
}

但上面的代码只能控制日期而不是时区的模式。 我也想更改时区。 谢谢!

【问题讨论】:

  • 为什么使用Date?我不知道 Gson 如何处理来自 java.time, the modern Java date and time API 的类型,但我知道 Date 设计不佳且早已过时。所以尽量避免。
  • 我暂时无法避免 Date,我想要合适的 Date 转换器和时区
  • 你想要哪个时区?因为Date 不能有时区而询问。你的字符串当然可以。
  • 在 GMT/UTC 时区
  • TimeZone.setDefault(TimeZone.getTimeZone("GMT+5"));这将改变洞申请时区。

标签: android date datetime timezone gson


【解决方案1】:

java.time

Date 类设计不佳且早已过时。我知道你暂时无法避免。可能您从尚未升级到现代 Java 日期和时间 API 的 java.time 的旧 API 获得了 Date

SimpleDateFormat 类更糟糕,它是一个臭名昭著的麻烦制造者。而你可以避免这个。

class DateConverter extends TypeAdapter<Date> {

    @Override
    public void write(JsonWriter out, Date date) throws IOException {
        if (date == null) {
            out.nullValue();
        } else {
            String dateTimeString = date.toInstant()
                    .atOffset(ZoneOffset.UTC)
                    .format(DateTimeFormatter.RFC_1123_DATE_TIME);
            out.value(dateTimeString);
        }
    }
}

java.time 甚至为您正在编写的格式提供了一个内置的格式化程序。所以没有必要编写我们自己的格式模式字符串,这很好,因为它总是一个容易出错的任务。我也喜欢代码中明确转换为 UTC 的事实。读者更清楚会发生什么。

链接: Oracle tutorial: Date Time 解释如何使用 java.time。

【讨论】:

    【解决方案2】:

    我的问题得到了解决方案。 我用TypeAdapter

    class DateConverter extends TypeAdapter<Date> {
    
        private SimpleDateFormat simpleDateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz");
    
        @Override
        public void write(JsonWriter out, Date date) throws IOException {
            if (date == null) {
                out.nullValue();
            } else {
                simpleDateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
                out.value(simpleDateFormat.format(date));
            }
        }
    }
    

    然后将此适配器设置为 Gson

    Gson gson = new GsonBuilder()
                    .registerTypeAdapter(Date.class, new DateConverter())
                    .create();
    
    Retrofit.Builder adapterBuilder = new Retrofit
    .Builder()
    .baseUrl(baseUrl)
    .addConverterFactory(GsonCustomConverterFactory.create(gson))
    

    感谢评论的帮助

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-03-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-24
      • 2013-01-17
      • 1970-01-01
      相关资源
      最近更新 更多