15

I cannot set properly the date format when using retrofit and trying to read a date like this:

2015-08-29T11:22:09.815479Z

An the GSON converter I'm setting is like this:

GsonConverter gsonConverter = new GsonConverter(
     new GsonBuilder()
            .setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSSSSz")
            .create()
);

Any clues on what's the problem?

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
Javier Manzano
  • 4,761
  • 16
  • 56
  • 86
  • Use the classes in the [java.time framework](http://docs.oracle.com/javase/8/docs/api/java/time/package-summary.html) built into Java 8 and later. They have a resolution of nanoseconds for up to nine digits of a fractional second. – Basil Bourque Mar 05 '16 at 02:27

2 Answers2

11

Java Date has millisecond precision so I've been creating the Gson object like so:

Gson gson = new GsonBuilder()
        .setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
        .create();

Of course, in a case like this, the microseconds are being truncated whether you put SSS or SSSSSS. It is also assumed that the last character of the converted string is always a Z.

To explain why your pattern didn't work, you used z (lowercase z) which according to the documentation represents a General Timezone (e.g., Pacific Standard Time; PST; GMT-08:00). Additionally, if you were to use Z (uppercase Z), it would also not work since it represents an RFC 822 time zone (e.g., -0800).

In another scenario where instead of the Z you have a time zone offset (e.g., -08, -0800, or -08:00), you can use X, XX, or XXX to represent an ISO 8610 time zone. But that requires Java 7 or 8 (I don't think Android is compatible with Java 8 at the moment).


Another method would be to write your own Gson Serializer and Deserializer; although I haven't tried.

It's also worth looking at java.sql.Timestamp class which is also supported by Gson and has more fine grained precision (nanoseconds) but it's also an option I haven't explored.

Matt Krause
  • 1,113
  • 14
  • 31
grim
  • 6,669
  • 11
  • 38
  • 57
  • Much of the java.time functionality built into Java 8 and later is back-ported to Java 6 & 7 in [ThreeTen-Backport](http://www.threeten.org/threetenbp/) and further adapted to [Android](https://en.wikipedia.org/wiki/Android_(operating_system)) in [ThreeTenABP](https://github.com/JakeWharton/ThreeTenABP) (see [*How to use…*](http://stackoverflow.com/q/38922754/642706)). – Basil Bourque Aug 27 '16 at 18:49
  • Is this really ISO 8601 compatible? I have never seen millis in the official spec. This looks like an extension of the standard format. – Christophe Roussy Jan 09 '18 at 09:49
  • 2
    @ChristopheRoussy While I've not read the ISO 8601 specification directly as it is copyrighted and expensive, according to [the Wikipedia page](https://en.wikipedia.org/wiki/ISO_8601): *There is no limit on the number of decimal places for the decimal fraction. However, the number of decimal places needs to be agreed to by the communicating parties.* In *java.time*, the various classes such as `Instant` resolve to nanoseconds (nine digits of decimal fraction). – Basil Bourque Oct 08 '19 at 05:44
  • 1
    I presume your formatting pattern here is ignoring the `Z` by enclosing in single-quote marks. This means you are **ignoring crucial information**: the offset-from-UTC or time zone. Likely to have bad effects, though I do not know exactly what the effects are in `GsonBuilder`. – Basil Bourque Oct 08 '19 at 05:48
4

Java 8 Instant class can be used to easily parse ISO-8601 timestamps without explicitly setting a format string, for example:

String input = "2018-11-07T00:25:00.073876Z";
Instant instant = Instant.parse(input);
AmitW
  • 798
  • 8
  • 11