在改造的 RequestBody 中转换 Date 的 TimeZone

Convert TimeZone of Date in RequestBody of retrofit

我正在使用改造来调用服务器,我有这样的 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);
    }
}

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

我找到了问题的解决方案。 我用了 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));
        }
    }
}

然后将此 Adapter 设置为 Gson

Gson gson = new GsonBuilder()
                .registerTypeAdapter(Date.class, new DateConverter())
                .create();

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

感谢评论中的帮助

java.time

Date class 设计不佳且早已过时。我知道你现在无法避免它。可能您从尚未升级到 java.time 的遗留 API、现代 Java 日期和时间 API.

获得了 Date

SimpleDateFormatclass更糟,是臭名昭著的捣蛋鬼。而你可以避免这个。

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 的事实。 reader 更清楚发生了什么。

Link: Oracle tutorial: Date Time 解释如何使用 java.time.