Android Retrofit:URL传递DateTime时的日期格式问题
解决Retrofit中URL路径参数日期格式问题
问题核心
Gson的setDateFormat仅负责JSON数据的序列化/反序列化,而URL路径中的@Path参数是独立处理的,因此直接配置Gson对路径里的日期参数完全无效。
方案一:使用Java 8+时间API(推荐)
Java原生Date类已过时,建议改用java.time.LocalDateTime(需时区则用ZonedDateTime),配合自定义转换器处理路径参数格式化:
- 替换API接口中的日期类型
@POST("api/updateStarted/{id}/{started}") suspend fun updateStarted( @Path("id") id: Int, @Path("started", encoded = false) started: LocalDateTime ): Response<Int>
必须加上
encoded = false,避免Retrofit自动转义我们已格式化好的日期字符串
- 编写自定义路径转换器
创建Converter.Factory实现LocalDateTime到目标格式字符串的转换:
class LocalDateTimePathConverter : Converter.Factory() { private val dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss") override fun stringConverter( type: Type, annotations: Array<Annotation>, retrofit: Retrofit ): Converter<*, String>? { return if (type == LocalDateTime::class.java) { Converter { value -> (value as LocalDateTime).format(dateFormatter) } } else null } }
- 配置Retrofit并添加转换器
注意删除你代码中重复添加的GsonConverterFactory.create()(会覆盖之前的日期格式配置):
val gson = GsonBuilder().setDateFormat("yyyy-MM-dd'T'HH:mm:ss").create() val apiClient: ApiClient = Retrofit.Builder() .addConverterFactory(GsonConverterFactory.create(gson)) .addConverterFactory(LocalDateTimePathConverter()) // 添加上自定义路径转换器 .baseUrl(API_BASE_URL) .client(getHttpClient(API_USERNAME, API_PASSWORD)) .build() .create(ApiClient::class.java)
方案二:继续使用Date类(不推荐)
如果必须保留Date类型,同样需要自定义路径转换器:
- 修改API接口
@POST("api/updateStarted/{id}/{started}") suspend fun updateStarted( @Path("id") id: Int, @Path("started", encoded = false) started: Date ): Response<Int>
- 编写Date转字符串的转换器
class DatePathConverter : Converter.Factory() { private val dateFormatter = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.US) override fun stringConverter( type: Type, annotations: Array<Annotation>, retrofit: Retrofit ): Converter<*, String>? { return if (type == Date::class.java) { Converter { value -> dateFormatter.format(value as Date) } } else null } }
- 添加到Retrofit构建器
和方案一一致,将自定义转换器加入Retrofit配置,同时清理重复的Gson转换器配置。
额外注意事项
- 若需要带时区的日期格式(如
2023-01-28T02:03:04+08:00),方案一可改用ZonedDateTime并调整格式化模板;方案二则为SimpleDateFormat设置对应时区。 - 务必确保
@Path参数的encoded = false配置,否则Retrofit会将日期中的T、:等字符转义为URL编码,导致格式不符合预期。
内容的提问来源于stack exchange,提问作者Kamil
相关产品推荐
相关产品推荐

