Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
200 views
in Technique[技术] by (71.8m points)

android - How to send Date formatted with Z and T to an API using Retrofit?

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?
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...