如何使用 Retrofit 将 Z 和 T 格式的日期发送到 API? [英] How to send Date formatted with Z and T to an API using Retrofit?
问题描述
我的 API 有以下示例路径 -
base_url/path/{country}/path/path?from=2020-03-01T00:00:00Z&to=2020-03-02T00:00:00Z
所以我需要使用 Z 和 T 格式传递 2 个 Date 对象,但我真的不知道如何将新的 Kotlin Date() 对象格式化为这些 Z 和 T 格式.
我目前的get方法-
@GET("path/{country}/path/path/")暂停乐趣 getCountryModelByDate(@Path("country") 国家:字符串,@Query("from") from : String,@Query("to") to : 字符串): 模型
但是当我尝试像下面这样测试我的方法时 -
class RemoteDataSource(private val api: Api) {暂停乐趣 getCountryModelByDate(): Resource{返回尝试{Resource.Success(coronaVirusApi.getCovidDeathsByDeathFromCountry(意大利",日期().toString(),日期().toString()))} 捕获(异常:异常){Resource.Exception(异常)}}}
这导致我收到以下 404 错误,请查看正在发送的 URL -
响应{protocol=h2, code=404, message=, url=https://api.covid19api.com/country/italy/status/deaths/?from=Tue%20Nov%2017%2010%3A47%3A30%20GMT%2B02%3A00%202020&to=Tue%20Nov%2017%2010%3A47%3A30%20GMT%2B02%3A00%202020}
所以我的问题是 -
- 如何将 Kotlin 日期对象格式化为我的 API 所需的 Z 和 T 格式?
- 如何将格式化的日期发送到我的查询中而不会被乱码?
Instant.toString() from java.time
T
和 Z
的格式是 ISO 8601.您可能需要查阅底部的链接.java.time 类,现代 Java 日期和时间 API,从它们的 toString
方法生成 ISO 8601.使用 Instant
类.对于 Java 的简短演示:
Instant i = Instant.now();System.out.println(i);
示例输出:
<块引用>2020-11-18T09:31:33.613965Z
如果 Instant
落在 UTC 的午夜,就像您一样,输出将如下所示:
2020-11-18T00:00:00Z
在第一种情况下,秒上小数的存在对您的 API 来说可能不是问题,因为根据 ISO 8601 标准,分数是可选的.如果您想摆脱它,最简单的方法是截断 Instant
:
Instant InstantToPrint = i.truncatedTo(ChronoUnit.SECONDS);System.out.println(instantToPrint);
<块引用>
2020-11-18T09:31:33Z
<块引用>
如何让即时对象始终返回 T00:00:00Z我的 API 需要什么?
鉴于您已经在 UTC 中获得了落在所需日期的瞬间,只需将其截断为整天:
Instant InstantToPrint = i.truncatedTo(ChronoUnit.DAYS);
<块引用>
2020-11-18T00:00:00Z
不过,问题是你的约会对象来自哪里.使用 java.time 日历中的一天将由 LocalDate
表示,因此我们需要进行转换.
LocalDate fromDate = LocalDate.of(2020, Month.MARCH, 1);即时 fromDateTimeUtc = fromDate.atStartOfDay(ZoneOffset.UTC).toInstant();System.out.println(fromDateTimeUtc);
<块引用>
2020-03-01T00:00:00Z
<块引用>
- 如何将格式化的日期发送到我的查询中而不会被乱码?
我认为 URL 中的冒号需要进行 URL 编码(协议后面的冒号除外,https://
中的冒号).所以它应该变成%3A
.Instant
中的字符串的其余部分应该清晰可读.
链接
- 维基百科文章:ISO 8601
- Oracle 教程:日期时间解释如何使用 java.time.
- Java 规范请求 (JSR) 310,其中
java.time
首先被描述. - ThreeTen Backport 项目,
java.time
的 backport 到Java 6 和 7(JSR-310 为 ThreeTen). - 可通过脱糖获得 Java 8+ API
- ThreeTenABP,ThreeTen Backport 安卓版
- 问题:如何在 Android 项目中使用 ThreeTenABP,与非常详尽的解释.
I have the following example path to my API -
base_url/path/{country}/path/path?from=2020-03-01T00:00:00Z&to=2020-03-02T00:00:00Z
So I need to pass 2 Date objects using the Z and T formatting and I can't really get how to format a new Kotlin Date() object into these Z and T formatting.
My current get method -
@GET("path/{country}/path/path/")
suspend fun getCountryModelByDate(
@Path("country") country: String,
@Query("from") from : String,
@Query("to") to : String
): Model
But when I try to test my method like the following -
class RemoteDataSource(private val api: Api) {
suspend fun getCountryModelByDate(): Resource<Model> {
return try {
Resource.Success(coronaVirusApi.getCovidDeathsByDeathFromCountry("italy", Date().toString(), Date().toString()))
} catch (exception: Exception) {
Resource.Exception(exception)
}
}
}
Which causes me to get the following 404 error, look at the URL that is being sent -
Response{protocol=h2, code=404, message=, url=https://api.covid19api.com/country/italy/status/deaths/?from=Tue%20Nov%2017%2010%3A47%3A30%20GMT%2B02%3A00%202020&to=Tue%20Nov%2017%2010%3A47%3A30%20GMT%2B02%3A00%202020}
So my questions are -
- How do I format a Kotlin Date object to have a Z and T format like what I need for my API?
- How can I send the formatted date into my query without it being gibrished out?
Instant.toString() from java.time
Your format with T
and Z
is ISO 8601. You may want to consult the link at the bottom. The classes of java.time, the modern Java date and time API, produce ISO 8601 from their toString
methods. Use the Instant
class. For a brief demonstration in Java:
Instant i = Instant.now();
System.out.println(i);
Example output:
2020-11-18T09:31:33.613965Z
If the Instant
falls on midnight in UTC, as yours do, the output will be like:
2020-11-18T00:00:00Z
The presence of decimals on the seconds in the first case probably is no issue for your API since the fraction is optional according to the ISO 8601 standard. Should you want to get rid of it, it’s easiest to truncate the Instant
:
Instant instantToPrint = i.truncatedTo(ChronoUnit.SECONDS);
System.out.println(instantToPrint);
2020-11-18T09:31:33Z
How can I make the instant object always return T00:00:00Z as this is what my API requires?
Edit: Given that you have already got an instant that falls on the desired day in UTC, just truncate to whole days:
Instant instantToPrint = i.truncatedTo(ChronoUnit.DAYS);
2020-11-18T00:00:00Z
The question is, though, where your date comes from. Using java.time a day in the calendar would be represented by a LocalDate
, so we’d need to convert.
LocalDate fromDate = LocalDate.of(2020, Month.MARCH, 1);
Instant fromDateTimeUtc = fromDate.atStartOfDay(ZoneOffset.UTC).toInstant();
System.out.println(fromDateTimeUtc);
2020-03-01T00:00:00Z
- How can I send the formatted date into my query without it being gibrished out?
I believe that a colon in a URL needs to be URL encoded (except the colon after the protocol, the one in https://
). So it should become %3A
. The rest of the string from Instant
should be clear to read.
Links
- Wikipedia article: ISO 8601
- Oracle tutorial: Date Time explaining how to use java.time.
- Java Specification Request (JSR) 310, where
java.time
was first described. - ThreeTen Backport project, the backport of
java.time
to Java 6 and 7 (ThreeTen for JSR-310). - Java 8+ APIs available through desugaring
- ThreeTenABP, Android edition of ThreeTen Backport
- Question: How to use ThreeTenABP in Android Project, with a very thorough explanation.
这篇关于如何使用 Retrofit 将 Z 和 T 格式的日期发送到 API?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!