如何使用 Retrofit 将 Z 和 T 格式的日期发送到 API? [英] How to send Date formatted with Z and T to an API using Retrofit?

查看:93
本文介绍了如何使用 Retrofit 将 Z 和 T 格式的日期发送到 API?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的 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}

所以我的问题是 -

  1. 如何将 Kotlin 日期对象格式化为我的 API 所需的 Z 和 T 格式?
  2. 如何将格式化的日期发送到我的查询中而不会被乱码?

解决方案

Instant.toString() from java.time

TZ 的格式是 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

<块引用>

  1. 如何将格式化的日期发送到我的查询中而不会被乱码?

我认为 URL 中的冒号需要进行 URL 编码(协议后面的冒号除外,https:// 中的冒号).所以它应该变成%3A.Instant 中的字符串的其余部分应该清晰可读.

链接

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 -

  1. How do I format a Kotlin Date object to have a Z and T format like what I need for my API?
  2. 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

  1. 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

这篇关于如何使用 Retrofit 将 Z 和 T 格式的日期发送到 API?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆