-1

I’m trying to send a parameter to an API that requires a date-time like >=2014-01-02T08:12:32Z (from the documentation).

To have this format, for what I know, I have to use something like this:

new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX").format(when)

But I’m getting an error from the API saying that the date is not valid.

The generated date is the following:

2021-05-21T20:08:14+02

For what I can see, the only format difference is the trailing Z that I thought was the timezone... what am I missing? What should I do to get that trailing "Z"?

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
Alberto Sinigaglia
  • 12,097
  • 2
  • 20
  • 48
  • I recommend you don’t use `SimpleDateFormat`. That class is notoriously troublesome and long outdated. Instead use `Instant` from [java.time, the modern Java date and time API,](https://docs.oracle.com/javase/tutorial/datetime/) and its `toString` method. See the answer by Basil Bourque. – Ole V.V. May 25 '21 at 02:50
  • Similar: [How to send Date formatted with Z and T to an API using Retrofit?](https://stackoverflow.com/questions/64872001/how-to-send-date-formatted-with-z-and-t-to-an-api-using-retrofit). Also: [How to get current moment in ISO 8601 format with date, hour, and minute?](https://stackoverflow.com/questions/3914404/how-to-get-current-moment-in-iso-8601-format-with-date-hour-and-minute) [The answer by Владимир Зайцев](https://stackoverflow.com/a/33218689/5772882) is best, and [the second answer by Basil Bourque](https://stackoverflow.com/a/50184308/5772882). – Ole V.V. May 25 '21 at 02:56

3 Answers3

3

tl;dr

java.time.Instant         // Represent a moment as seen with an offset-from-UTC of zero hours-minutes-seconds.
.now()                    // Capture the current moment.
.truncatedTo(             // Lop off any fractional second.
    ChronoUnit.SECONDS    // An enum specifying the granularity of truncation.
)                         // Returns another `Instant` object rather than altering the original, per immutable-objects pattern.
.toString()               // Generate text representing the content of this object, using standard ISO 8601 format.

2021-05-25T01:05:03Z

Details

Avoid legacy date-time classes

You are using terrible date-time classes that were supplanted years ago by the modern java.time classes.

java.time

To capture the current moment as seen in UTC, use Instant.now.

So:

Instant.now().toString()

… is all you need.

See this code run live at IdeOne.com.

2021-05-25T01:05:03.208937Z

The Z on the end means an offset-from-UTC of zero hours-minutes-seconds. Pronounced “Zulu”. Equivalent to +00:00.

Truncation

If you just want the whole seconds only, and drop the fractional second, truncate.

  Instant.now().truncatedTo( ChronoUnit.SECONDS ).toString() 

See the code run live at IdeOne.com.

2021-05-25T01:05:03Z

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
2

Z is the time zone, but perhaps the recipient only supports Z. It is not unheard of.

To get the time adjusted, simply specify the desired time zone in the formatter.

// Simulate question's time zone
TimeZone.setDefault(TimeZone.getTimeZone("GMT+02"));

// Set `when` and show it for proof
Date when = Date.from(OffsetDateTime.parse("2021-05-21T20:08:14+02").toInstant());
System.out.println(when);
// Output: Fri May 21 20:08:14 GMT+02:00 2021

// See that question code generates same output
System.out.println(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX").format(when));
// Output: 2021-05-21T20:08:14+02

// Add desired time zone to formatter
SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX");
fmt.setTimeZone(TimeZone.getTimeZone("UTC"));
System.out.println(fmt.format(when));
// Output: 2021-05-21T18:08:14Z   (note how hour was changed from 20 to 18)

I would however recommend you start using the Time API added in Java 8.

// Set `when` and show it for proof
OffsetDateTime when = OffsetDateTime.parse("2021-05-21T20:08:14+02");
System.out.println(when);
// Output: 2021-05-21T20:08:14+02:00

// See same output as question
System.out.println(when.format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssX")));
// Output: 2021-05-21T20:08:14+02

// Option 1: Add desired time zone to formatter
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssX")
        .withZone(ZoneOffset.UTC);
System.out.println(fmt.format(when));
// Output: 2021-05-21T18:08:14Z

// Option 2: Change time zone of value
OffsetDateTime whenUTC = when.atZoneSameInstant(ZoneOffset.UTC).toOffsetDateTime();
System.out.println(whenUTC);
// Output: 2021-05-21T18:08:14Z
Andreas
  • 154,647
  • 11
  • 152
  • 247
  • so since I'm in +2 timezone, and they want the date as Z, I should see in the debugger that the URL contains when-2 hours? – Alberto Sinigaglia May 24 '21 at 22:11
  • @Berto99 Unknown if that's what the server wants. It is what is should want, but some people don't understand what `Z` means and simply ignores it, in which case you don't want the hour to be adjusted. This answer covers how it *should* work. --- If the server is flawed, and wants the hour as-is (e.g. 20, not 18), then simply replace the `X` in the question code with `'Z'` *(quotes required)*. – Andreas May 24 '21 at 22:21
1

You can see an example here https://howtodoinjava.com/java/date-time/java-date-formatting/

import java.text.SimpleDateFormat;
import java.util.Date;
 
public class JavaDateValidations 
{
    public static final String TIMESTAMP_PATTERN 
                            = "yyyy-MM-ddTHH:mm:ss"; 
 
    public static void main(String[] args) 
    {
        SimpleDateFormat sdf = new SimpleDateFormat(TIMESTAMP_PATTERN);
         
        Date date = new Date();
         
        String formattedDate = sdf.format(date);
        System.out.println(formattedDate);      //2020-05-09T00:32:28
    }
}
Peachcat
  • 17
  • 4
  • 1
    Not really a useful answer. OP is clearly asking about the timezone, so it must be important for them to have an answer that includes the timezone. – Dawood ibn Kareem May 24 '21 at 22:58